1

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?

XrXr
  • 2,027
  • 1
  • 14
  • 20
  • 2
    Even in the IO monad, what is guaranteed is that the effects of the IO actions are sequenced in order. Evaluation order is still unknown, e.g. `print (1+2) ; print (3+4)` does not force an execution ordering between the sums. Note that even in low-level languages such as C there would be no ordering guarantee: the compiler would be free to evaluate any sum first, since they have no side effects. In a purely functional language, no-side-effects is the norm (unlike C), so even more ordering options are made available to the compiler (e.g. `print (f 1); print (f 2)` can call `f` in any order). – chi Mar 07 '15 at 01:16
  • @chi I think for a code like this: `print (1 + 2) >> exitSuccess >> print (3 + undefined)`, the output will be always `3 *** Exception: ExitSuccess`. `3 + undefined` will never be evaluated because of lazy evaluation unless the monadic action forces it. What do you think ? – Sibi Mar 07 '15 at 22:54
  • @Sibi Yes, I would expect GHC to do that. But, theoretically speaking, GHC could use some static analysis to guarantee that `3+4` is error-free (total) and reorder / parallelize its execution. Or just reorder suppressing exceptions. The main showstopper to this approach AFAICS is that it is not always an optimization: sometimes optimistic evaluation can lead to memory leaks :-/ – chi Mar 07 '15 at 23:29

1 Answers1

6

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".

Sibi
  • 47,472
  • 16
  • 95
  • 163
  • 1
    This seems to me like it just distracts from the actual question, since evaluation order isn't relevant here. You could just as well write `do {let {x = undefined}; y <- Nothing; return $ x + y}`, and get the same result, but this has nothing to do with the order of evaluation of the two statements. – amalloy Mar 07 '15 at 02:17
  • @amalloy I have expanded the answer to include more details. Let me know if this improves or else I will try to expand it more. – Sibi Mar 07 '15 at 21:20