I was reading https://wiki.haskell.org/Do_notation_considered_harmful and was surprised to read the following lines
Newcomers might think that the order of statements determines the order of execution. ... The order of statements is also not the criterion for the evaluation order.
The wiki post gave some examples that demonstrate this property. While the examples make sense, I still don't fully believe that the statement is true, since if I write something like
main = do
putStrLn "foo"
putStrLn "bar"
putStrLn "baz"
The three lines come out in the order of the statements. So what exactly is going on here?
What it says is that the order of statements doesn't influence the evaluation criteria. As @chi points out in IO monad effects are sequenced in order but their evaluation order is still not known. An example of a monad which will make the concept clear:
test = do
x <- Just (2 + undefined)
y <- Nothing
return (x + y)
In ghci:
λ> test
Nothing
The above code has three statements. It can be de-sugared into the following form:
Just (2 + undefined) >>= \x -> Nothing >>= \y -> return (x + y)
Now since (>>=)
is left associative, it will be evaluated like this:
(Just (2 + undefined) >>= \x -> Nothing) >>= \y -> return (x + y)
Note that Maybe
monad is defined like this:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing -- A failed computation returns Nothing
(Just x) >>= f = f x -- Applies function f to value x
Applying the value (2 + undefined)
to the function \x -> Nothing
will result in Nothing
.
The expression 2 + undefined
is unevaluated, thanks to lazy evaluation strategy followed by Haskell.
Now we have a reduced form:
Nothing >>= \y -> return (2 + undefined + y)
Looking at the Monad
instance for it, you can see that this will produce Nothing
because Nothing >>= _ = Nothing
.
What if the argument was strict instead:
test = do
!x <- Just (2 + undefined)
y <- Nothing
return (y + x)
Demo in ghci
:
λ> test
*** Exception: Prelude.undefined
If we follows strict evaluation procedure, then you can see that order actually matters. But in a lazy setting, the order of statements doesn't matter. And hence the wiki claims, "the order of statements is not the criterion for the evaluation order".