[Haskell-cafe] Execution order in IO

silvio silvio.frischi at gmail.com
Wed Apr 15 13:06:00 UTC 2015


> With lazy evaluation where is it written that if you write things
> with no dependencies with a "do" things will be done in order ? Or
> isn't it ?

Since Haskell is purely functional the evaluation order shouldn't matter
unless you do IO or for efficiency purposes.

In general you can use "seq :: a -> b -> b" or Bang patterns (!) to
control execution order. "seq" will evaluate "a" to Weak Head Normal
Form (WHNF) and then return "b". WHNF just means it will evaluate until
it finds a Constructor. In the case of lists for instance it will see if
your value is ":" or "[]".

Now you can use that to implement your monads. For the state monad for
instance there is a strict and a "lazy" version.

newtype State s a = State { runState :: s -> (a,s) }

instance Monad (State s) where
    act1 >>= f2  = State $ \s1 -> runState (f2 input2) s2 where
	(input2, s2) = runState act1 s1

instance Monad (State s) where
    act1 >>= f2  = State $ \s1 -> s2 `seq` runState (f2 input2) s2 where
	(input2, s2) = runState act1 s1

You can see in the second implementation s2 has to be evaluated to WHNF.
So the runState on the 3rd line has to be evaluated before the runState
on the 2nd line.

> Is it something in the implementation of IO ?

In the case of IO monad you are almost guaranteed that things get
executed in order. The one exception is (unsafeInterleaveIO :: IO a ->
IO a). This will only be evaluated when you use the result (use the
result means make a case statement to see which constructor it is. e.g.
":" or "[]"). LazyIO probably also uses unsafeInterleaveIO and should in
my opinion be called unsafeIO. The problem with unsafeInterleaveIO is
that you have to catch the IOErrors at arbitrary places. For instance,
you can get a read error when looking at a part of a string because the
reading was delayed until you look at it.

> Is the do keyword more than just a syntactic sugar for a string of
> binds and lambdas ?

No, "do" is not more than syntactic sugar. The way to control execution
order is "seq" and bang patterns.

Hope this helps

Silvio




More information about the Haskell-Cafe mailing list