
Let's just have a look at the monad instance of IO which is defined in the files ghc-prim/GHC/Types.hs and base/GHC/Base.hs newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #)) instance Monad IO where ... (>>=) = bindIO ... bindIO :: IO a -> (a -> IO b) -> IO b bindIO (IO m) k = IO $ \ s -> case m s of (# new_s, a #) -> unIO (k a) If you can forget for a minute about all the # you will end up with this. newtype IO a = IO (RealWorld -> (RealWorld, a)) bindIO (IO m) k = IO $ \ s -> case m s of (new_s, a) -> unIO (k a) when the following part is evaluated: case m s of (new_s, a) -> unIO (k a) (m s) has to be evaluated first in order to ensure that the result matches the pattern (new_s, a) and is not bottom/some infinite calculation/an error. This is why IO statements are evaluated in order. Silvio