Does Haskell's 'evaluate' reduce to normal or WHNF?

264 views Asked by At

I understand (I think) that Haskell's seq, will (generally) reduce its first argument to WHNF, and see this behavior as expected in GHCi:

λ> let x = (trace "foo" Foo (trace "bar" Bar 100)) in seq x 0
foo
0

However, though the documentation for evaluate says that it also reduces its argument to WHNF, it looks like it actually fully reduces its argument to normal form:

λ> let x = (trace "foo" Foo (trace "bar" Bar 100)) in evaluate x
foo
Foo bar
(Bar 100)

I can confirm this (apparent) discrepancy with

λ> let y = (trace "foo" Foo (trace "bar" Bar 100))
λ> seq y 0
foo
0
λ> :sprint y
y = <Foo> _

and

λ> let z = (trace "foo" Foo (trace "bar" Bar 100))
λ> evaluate z
foo
Foo bar
(Bar 100)
λ> :sprint z
z = <Foo> (<Bar> 100)

If the documentation for evaluate is correct, shouldn't the behavior of seq and evaluate be the same? What am I missing here (as a Haskell beginner)?

1

There are 1 answers

1
Ørjan Johansen On BEST ANSWER

What you are missing is that GHCi also prints the result of IO actions (if they can be shown and are not ()), which does cause it to evaluate to normal form. Try instead:

λ> let x = (trace "foo" Foo (trace "bar" Bar 100)) in evaluate x >> return ()
foo