That's due to two
's type. Lets check all the type's so far:
ghci> :t foo
foo :: Foo
ghci> :t two
two :: Num a => a
Aha! two
is polymorphic. Therefore, its behaviour depends on the actual Num
instance. Therefore, it needs to get re-evaluated in g
. We can check this by using :sprint
:
ghci> :sprint foo
foo = Foo _ -- simplified
Which indicates that we never looked at the contents of Foo
. foo
is in weak head normal form. This answers your second question. But back to your first. What happens on :sprint two
?
ghci> :sprint two
two = _
As you can see, due to its polymorphic nature, two
doesn't get to WHNF. After all, which WHNF should it take? You might want to use it as Integer
, or Currency
, or Complex Triple
.
This is, by the way, a reason for the existence of the monomorphism restriction, see "A History of Haskell", section 6.2:
6.2 The monomorphism restriction
A major source of controversy in the early stages was the so-called
“monomorphism restriction.” Suppose that genericLength
has
this overloaded type:
genericLength` :: Num a => [b] -> a
Now consider this definition:
f xs = (len, len)
where
len = genericLength xs
It looks as if len should be computed only once, but it can actually be computed twice. Why? Because we can infer the type
len :: (Num a) => a
; when desugared with the dictionary-
passing translation, len
becomes a function that is called once
for each occurrence of len
, each of which might used at a different
type.
See also this Q&A for more information about the restriction.
That being said, we can easily change this if we fix two
's type:
ghci> let foo = trace "foo" Foo (trace "bar" Bar 100)
ghci> let two = trace "two" (2 :: Integer)
ghci> let g (Foo x) y = y
Now the output will be exactly as you've expected. Alternatively, you can enable the monomorphism restriction with :set -XMonomorphismRestriction
, as it is disabled in current GHCi versions by default:
ghci> :set -XMonomorphismRestriction
ghci> let two = trace "two" 2
ghci> :t two
two :: Integer -- due to defaulting rules