We’ve seen many monads already. We know that every monad specifies a way to combine two computations in a sequence by implementing the >>= operator. We also know that in a monadic setting we have a result of a computation with some additional effects: computations may fail (as in the Maybe monad) or give an opportunity to communicate with the real world by doing input and output (as in the IO monad), or we may mutate the state or consult an environment in some other effectful computations. There are many other monads, but we already know what all of them share in common.
In this chapter, we’ll discuss one simple question: how do we express computations that need to use more than one monadic effect at the same time? We’ll start with exploring the problem. We’ll solve a problem in one monad, find some flaws in that solution, and try to fix them. In Haskell it is often the case that there is a monad for this. But we have a monad already, so the problem now is how to add another monad to a solution. Let’s see.