3

Given this line of code (which I first saw in this answer):

pVal :: Num a => a
pVal = sum . map fromIntegral $ ([1..10000000] :: [Int])

If it's used as multiple types, is the expression completely reevaluated for each type? Is one result for each type kept around?

For example:

pInt :: Int
pInt = pVal

pDub :: Double
pDub = pVal
Community
  • 1
  • 1
Matt Fenwick
  • 48,199
  • 22
  • 128
  • 192
  • This might be a dupe of http://stackoverflow.com/questions/4179453/why-are-polymorphic-values-not-inferred-in-haskell. Should I delete? – Matt Fenwick Oct 05 '12 at 12:48
  • As an appendix to hammar's answer: when you're using it at a specific type in a programme, the compiler might share the value for that type between uses. In simple cases at least, GHC does that when optimisations are enabled. So if you use it at types `Int` and `Integer`, GHC will often produce specialised top-level values `pVal_s :: Integer`, `pVal_s1 :: Int` and rewrite rules to use those instead of the polymorphic `pVal`. But I don't know what the heuristics are, when it is deemed worthwhile to create a specialisation. – Daniel Fischer Oct 05 '12 at 14:17

1 Answers1

12

Technically, the Haskell standard doesn't specify. In practice, it's re-evaluated each time. You can verify this yourself using Debug.Trace:

import Debug.Trace (trace)

pVal :: Num a => a
pVal = trace "evaluating..." $ sum . map fromIntegral $ ([1..10000] :: [Int])

Try it in GHCi:

> pVal :: Int
evaluating...
50005000
> pVal :: Int
evaluating...
50005000

However, binding this value to a concrete type will allow it to be re-used.

pInt :: Int
pInt = pVal

Notice there's no "evaluating..." the second time:

> pInt
evaluating...
50005000
> pInt
50005000
hammar
  • 138,522
  • 17
  • 304
  • 385