The author tries to say that the composition of any two monads isn't possible. This isn't because language is bad, but because there are monads whose composition isn't a monad.

For instance, IsntMonad isn't a monad:

newtype IsntMonad a = IsntMonad (Maybe (IO a)) instance Monad IsntMonad where m >>= k = ???

But, IsMonad is a monad:

newtype IsMonad a = IsMonad { runIsMonad :: IO (Maybe a) } instance Monad IsMonad where (IsMonad ioma) >>= k = IsMonad $ do ma <- ioma case ma of Just a -> runIsMonad $ k a Nothing -> return Nothing

So, monad transformers it's just a way to make possibility of composition. But how it works, if we know that it isn't possible in general case? Yes, it's not possible for any two monads, but it's possible for some concrete monad and any other monad.

So, there are monads which can be compose with any other monad. Such monads in the first approximation are monad transformers.

For instance, the monad Maybe can be compose with any other monad like this: Monad m => m (Maybe a) , so m (Maybe a) is a monad. But how we can do instance of monad for it?

instance Monad m => Monad ??? where ...

Then MaybeT appears as helper, it is called a monad transformer (the suffix T hints on that).

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } instance Monad m => Monad (MaybeT m) where m >>= k = MaybeT $ do ma <- runMaybeT m case ma of Just a -> runMaybeT $ k a Nothing -> return Nothing

After that, automatically MaybeT IO , MaybeT [] , MaybeT STM ... are monads. You don't need to write instances for them. This is what they are good for.

We understood what monad transformers are just way to composition of monads. But it isn't an answer on: What is the composition of monads good for? Why did we spend our time and energy on finding a way to combine monads?

Well, as you known, any monad associated with some sort of effects. If we compose two monads we also compose them effects and this result we will be get automatically.

For example:

StateT s Maybe a -- a computation with a state `s` which can fail ReaderT e Maybe a -- a computation with access to an environment `e` and option to fail ReaderT e (StateT s Maybe) a -- a computation with state `s`, access to an environment `e` and option to fail ...

Composition of monads isn't commutative. For example, MaybeT (State s) isn't same thing as StateT s Maybe . A simple way to understand what effects will be produced by the composition is to remember that effects are produced from the inner monad to the outer monad. MaybeT (State s) the first effect will be produced by State s monad then by Maybe . But in StateT s Maybe the first effect will be produced by Maybe then by State s . This means that in cases of failure in StateT s Maybe , we lose state, but in MaybeT (State s) we save the state in which the error occurred.

So, the composition of monads is a simple way to build more complex monads just on type level.

How can this be applied in practice? For example, let's image situation. You have something and options to transform it. Imperative code can look like this:

thing = defaultValue; if (transformByOption0) doTransformationByOption0(thing); if (transformByOption1) doTransformationByOption1(thing); ...

In Haskell we can write:

thing <- flip execStateT defaultValue $ do when transformByOption0 $ modify doTransformationByOption0 when transformByOption1 $ modify doTransformationByOption1 when transformByOption2 $ put =<< doMonadicTransformationByOption2 =<< get ...