
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