Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)?

like image 781
orome Avatar asked Oct 12 '15 14:10

orome


People also ask

Can one decide whether a term has a weak head normal form?

To determine whether an expression is in weak head normal form, we only have to look at the outermost part of the expression. If it's a data constructor or a lambda, it's in weak head normal form. If it's a function application, it's not.

What is normal form Haskell?

From HaskellWiki. An expression is in weak head normal form (WHNF), if it is either: a constructor (eventually applied to arguments) like True , Just (square 42) or (:) 1 . a built-in function applied to too few arguments (perhaps none) like (+) 2 or sqrt . or a lambda abstraction \x -> expression .

What is SEQ in Haskell?

From HaskellWiki. The seq function is the most basic method of introducing strictness to a Haskell program. seq :: a -> b -> b takes two arguments of any type, and returns the second. However, it also has the important property that it is magically strict in its first argument.


1 Answers

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
like image 150
Ørjan Johansen Avatar answered Oct 04 '22 21:10

Ørjan Johansen