
And this is because the implementation of IO is *specifically* crafted to guarantee this ordering. It is not a property of monads in general, or do syntax in general.
Is it? The example main = do a <- getLine b <- getLine let c = foo a b -- I guess you'd want to do something about a and b eventually isn't really representative of monads, as it could be done just as well with the applicative functor interface (and apparently there are plans for GHC 7.12 to figure it out on its own). Applicative instance for IO indeed does order effects left to right, so this could be used as an example of "specific crafting". Changing it to, let's say main = do a <- getLine b <- getLine c <- foo a b makes it obvious there's no way to evaluate c before a and b, whatever monad that would be, as foo may c can change the shape of the monad anyway it pleases. For example if the monad in question was Maybe, there would be no way to tell whether foo returns Just or Nothing without actually evaluating it. (a and b could still be reordered, but again, this is a feature of an applicative functor, which all monads must derive from, but not of the monadic interface as of itself) Best regards, Marcin Mrotek