A monad transformer makes new monad out of an existing monad, such
that computations of the old monad may be embedded in the new one.
To construct a monad with a desired set of features, one typically
starts with a base monad, such as Identity, [] or IO, and
applies a sequence of monad transformers.

Most monad transformer modules include the special case of applying the
transformer to Identity. For example, State s is an abbreviation
for StateT s Identity.

Each monad transformer also comes with an operation runXXX to
unwrap the transformer, exposing a computation of the inner monad.

Examples

Parsing

One might define a parsing monad by adding a state, consisting of the
String remaining to be parsed, to the [] monad, which provides
non-determinism:

import Control.Monad.Trans.State
type Parser = StateT String []

Then Parser is an instance of MonadPlus: monadic sequencing implements
concatenation of parsers, while mplus provides choice.
To use parsers, we need a primitive to run a constructed parser on an
input string:

Finally, we need a primitive parser that matches a single character,
from which arbitrarily complex parsers may be constructed:

item :: Parser Char
item = do
c:cs <- get
put cs
return c

In this example we use the operations get and put from
Control.Monad.Trans.State, which are defined only for monads that are
applications of StateT. Alternatively one could use monad classes
from other packages, which contain methods get and put with types
generalized over all suitable monads.

Parsing and counting

We can define a parser that also counts by adding a WriterT transformer:

To define item parser, we need to lift the StateT operations through
the WriterT transformers.

item :: Parser Char
item = do
c:cs <- lift get
lift (put cs)
return c

In this case, we were able to do this with lift, but operations with
more complex types require special lifting functions, which are provided
by monad transformers for which they can be implemented. If you use
one of packages of monad classes, this lifting is handled automatically
by the instances of the classes, and you need only use the generalized
methods get and put.