A monad transformer makes a 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.

Conventions

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 runXXXT to
unwrap the transformer, exposing a computation of the inner monad.
(Currently these functions are defined as field labels, but in the next
major release they will be separate functions.)

All of the monad transformers except ContT
are functors on the category of monads: in addition to defining a
mapping of monads, they also define a mapping from transformations
between base monads to transformations between transformed monads,
called mapXXXT. Thus given a monad transformation t :: M a -> N a,
the combinator mapStateT constructs
a monad transformation

mapStateT t :: StateT s M a -> StateT s N a

For these monad transformers, lift is a natural transformation in the
category of monads, i.e. for any monad transformation t :: M a -> N a,

Each of the monad transformers introduces relevant operations.
In a sequence of monad transformers, most of these operations.can be
lifted through other transformers using lift or the mapXXXT
combinator, but a few with more complex type signatures require
specialized lifting combinators, called liftOp
(see Control.Monad.Signatures).

Strict monads

A monad is said to be strict if its >>= operation is strict in its first
argument. The base monads Maybe, [] and IO are strict:

In a strict monad you know when each action is executed, but the monad
is not necessarily strict in the return value, or in other components
of the monad, such as a state. However you can use seq to create
an action that is strict in the component you want evaluated.

Examples

Parsing

One might define a parsing monad by adding a state (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 the mtl package or similar, 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 the item parser, we need to lift the
StateT operations through the
WriterT transformer.

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 the
monad classes of the mtl package or similar, this lifting is handled
automatically by the instances of the classes, and you need only use
the generalized methods get and put.

We can also define a primitive using the Writer:

tick :: Parser ()
tick = tell (Sum 1)

Then the parser will keep track of how many ticks it executes.

Interpreter monad

Suppose we want to define an interpreter that can do I/O and has
exceptions, an environment and a modifiable store. We can define
a monad that supports all these things as a stack of monad transformers:

Now we would like to be able to use the operations associated with each
of those monad transformers on InterpM actions. Since the uppermost
monad transformer of InterpM is StateT,
it already has the state operations get and set.

The first of the ReaderT operations,
ask, is a simple action, so we can lift it
through StateT to InterpM using lift:

We also wish to lift the operations of ExceptT
through both ReaderT and
StateT. For the operation
throwE, we know throwE e is a simple
action, so we can lift it through the two monad transformers to InterpM
with two lifts:

throwE :: Err -> InterpM a
throwE e = lift (lift (E.throwE e))

The catchE operation has a more
complex type, so we need to use the special-purpose lifting function
liftCatch provided by most monad transformers. Here we use
the ReaderT version followed by the
StateT version: