If monads are the solution, what is the problem?
The more I've learned about Haskell, the more I've come to realize that Haskell's approach to IO really has very little to do with Monads. Fundamentally, Haskell implementations sequence IO actions using hidden magic. (GHC uses dummy world variables.) As it happens, the operations for constructing IO actions from pure values and for sequencing IO actions form a Monad. But that's not really any more interesting than the fact that e.g. (\x -> [x]) and concatMap form a Monad.