Haskell/Monad transformers
We've seen that monads are used for handling IO
actions, Maybe
, lists, and state. With monads providing such useful generalpurpose functionalities, we might like to use the capabilities of several monads at once. For instance, a function could use both I/O and Maybe
exception handling. A type like IO (Maybe a)
could work, but that forces us to do pattern matching within the do
blocks to extract values, and monads are supposed to work without that.
Enter monad transformers: special types that allow us to roll two monads into a single one that shares the behavior of both.
Passphrase validation[edit]
Consider a reallife problem for IT staff worldwide: getting users to create strong passphrases. One approach: force the user to enter a minimum length with various irritating requirements (such as at least one capital letter, one number, one nonalphanumeric character, etc.)
Here's a Haskell function to acquire a passphrase from a user:
getPassphrase :: IO (Maybe String) getPassphrase = do s < getLine if isValid s then return $ Just s else return Nothing  The validation test could be anything we want it to be. isValid :: String > Bool isValid s = length s >= 8 && any isAlpha s && any isNumber s && any isPunctuation s
First and foremost, getPassphrase
is an IO
action, as it needs to get input from the user. We also use Maybe
, as we intend to return Nothing
in case the password does not pass the isValid
. Note, however, that we aren't actually using Maybe
as a monad here: the do
block is in the IO
monad, and we just happen to return
a Maybe
value into it.
Monad transformers not only make it easier to write getPassphrase
but also simplify all the code instances. Our passphrase acquisition program could continue like this:
askPassphrase :: IO () askPassphrase = do putStrLn "Insert your new passphrase:" maybe_value < getPassphrase if isJust maybe_value then do putStrLn "Storing in database..."  ... other stuff, including 'else'
The code uses one line to generate the maybe_value
variable followed by further validation of the passphrase.
With monad transformers, we will be able to extract the passphrase in one go — without any pattern matching or equivalent bureaucracy like isJust
. The gains for our simple example might seem small but will scale up for more complex situations.
A simple monad transformer: MaybeT
[edit]
To simplify getPassphrase
and all the code that uses it, we will define a monad transformer that gives the IO
monad some characteristics of the Maybe
monad; we will call it MaybeT
. That follows a convention where monad transformers have a "T
" appended to the name of the monad whose characteristics they provide.
MaybeT
is a wrapper around m (Maybe a)
, where m
can be any monad (IO
in our example):
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
This data type definition specifies a MaybeT
type constructor, parameterized over m
, with a term constructor, also called MaybeT
, and a convenient accessor function runMaybeT
, with which we can access the underlying representation.
The whole point of monad transformers is that they are monads themselves; and so we need to make MaybeT m
an instance of the Monad
class:
instance Monad m => Monad (MaybeT m) where return = MaybeT . return . Just
It would also have been possible (though arguably less readable) to write return = MaybeT . return . return
.
As in all monads, the bind operator is the heart of the transformer.
 The signature of (>>=), specialized to MaybeT m (>>=) :: MaybeT m a > (a > MaybeT m b) > MaybeT m b x >>= f = MaybeT $ do maybe_value < runMaybeT x case maybe_value of Nothing > return Nothing Just value > runMaybeT $ f value
Starting from the first line of the do
block:
 First, the
runMaybeT
accessor unwrapsx
into anm (Maybe a)
computation. That shows us that the wholedo
block is inm
.  Still in the first line,
<
extracts aMaybe a
value from the unwrapped computation.  The
case
statement testsmaybe_value
: With
Nothing
, we returnNothing
intom
;  With
Just
, we applyf
to thevalue
from the Just. Sincef
hasMaybeT m b
as result type, we need an extrarunMaybeT
to put the result back into them
monad.
 With
 Finally, the
do
block as a whole hasm (Maybe b)
type; so it is wrapped with theMaybeT
constructor.
It may look a bit complicated; but aside from the copious amounts of wrapping and unwrapping, the implementation does the same as the familiar bind operator of Maybe
:
 (>>=) for the Maybe monad maybe_value >>= f = case maybe_value of Nothing > Nothing Just value > f value
Why use the MaybeT
constructor before the do
block while we have the accessor runMaybeT
within do
? Well, the do
block must be in the m
monad, not in MaybeT m
(which lacks a defined bind operator at this point).
Note
The chained functions in the definition of return
suggest a metaphor, which you may find either useful or confusing. Consider the combined monad as a sandwich. This metaphor might suggest three layers of monads in action, but there are only two really: the inner monad and the combined monad (there are no binds or returns done in the base monad; it only appears as part of the implementation of the transformer). If you like this metaphor at all, think of the transformer and the base monad as two parts of the same thing  the bread  which wraps the inner monad.
Technically, this is all we need; however, it is convenient to make MaybeT
an instance of a few other classes:
instance Monad m => MonadPlus (MaybeT m) where mzero = MaybeT $ return Nothing mplus x y = MaybeT $ do maybe_value < runMaybeT x case maybe_value of Nothing > runMaybeT y Just _ > return maybe_value instance MonadTrans MaybeT where lift = MaybeT . (liftM Just)
MonadTrans
implements the lift
function, so we can take functions from the m
monad and bring them into the MaybeT m
monad in order to use them in do
blocks. As for MonadPlus
, since Maybe
is an instance of that class it makes sense to make the MaybeT
an instance too.
Application to the passphrase example[edit]
With all this done, here is what the previous example of passphrase management looks like:
getValidPassphrase :: MaybeT IO String getValidPassphrase = do s < lift getLine guard (isValid s)  MonadPlus provides guard. return s askPassphrase :: MaybeT IO () askPassphrase = do lift $ putStrLn "Insert your new passphrase:" value < getValidPassphrase lift $ putStrLn "Storing in database..."
The code is now simpler, especially in the user function askPassphrase
. Most importantly, we do not have to manually check whether the result is Nothing
or Just
: the bind operator takes care of that for us.
Note how we use lift
to bring the functions getLine
and putStrLn
into the MaybeT IO
monad. Also, since MaybeT IO
is an instance of MonadPlus
, checking for passphrase validity can be taken care of by a guard
statement, which will return mzero
(i.e. IO Nothing
) in case of a bad passphrase.
Incidentally, with the help of MonadPlus
it also becomes very easy to ask the user ad infinitum for a valid passphrase:
askPassword :: MaybeT IO () askPassword = do lift $ putStrLn "Insert your new password:" value < msum $ repeat getValidPassphrase lift $ putStrLn "Storing in database..."
A plethora of transformers[edit]
The transformers package provides modules with transformers for many common monads (MaybeT
, for instance, can be found in Control.Monad.Trans.Maybe). These are defined consistently with their nontransformer versions; that is, the implementation is basically the same except with the extra wrapping and unwrapping needed to thread the other monad. From this point on, we will use base monad to refer to the nontransformer monad on which a transformer is based and inner monad to refer to the other monad on which the transformer is applied.
To pick an arbitrary example, ReaderT Env IO String
is a computation which involves reading values from some environment of type Env
(the semantics of Reader
, the base monad) and performing some IO
in order to give a value of type String
. Since the bind operator and return
for the transformer mirror the semantics of the base monad, a do
block of type ReaderT Env IO String
will, from the outside, look a lot like a do
block of the Reader
monad except that IO
actions become trivial to embed by using lift
.
Type juggling[edit]
We have seen that the type constructor for MaybeT
is a wrapper for a Maybe
value in the inner monad. So, the corresponding accessor runMaybeT
gives us a value of type m (Maybe a)
 i.e. a value of the base monad returned in the inner monad. Similarly, for the list and error transformers:
runListT :: ListT m a > m [a]
and
runErrorT :: ErrorT e m a > m (Either e a)
Not all transformers are related to their base monads in this way, however. Unlike the base monads in the examples above, the Writer
, Reader
, State
, and Cont
monads have neither multiple constructors nor constructors with multiple arguments. For that reason, they have run... functions which act as simple unwrappers analogous to the run...T of the transformer versions. The table below shows the result types of the run... and run...T functions in each case, which may be thought of as the types wrapped by the base and transformed monads respectively.^{[1]}
Base Monad  Transformer  Original Type ("wrapped" by base) 
Combined Type ("wrapped" by transformer) 

Writer  WriterT  (a, w) 
m (a, w) 
Reader  ReaderT  r > a 
r > m a 
State  StateT  s > (a, s) 
s > m (a, s) 
Cont  ContT  (a > r) > r 
(a > m r) > m r 
Notice that the base monad is absent in the combined types. Without interesting constructors (of the sort for Maybe
or lists), there is no reason to retain the base monad type after unwrapping the transformed monad. Anyway, in the three latter cases we have function types being wrapped. StateT
, for instance, turns statetransforming functions of the form s > (a, s)
into statetransforming functions of the form s > m (a, s)
; only the result type of the wrapped function goes into the inner monad. ReaderT
is analogous.ContT
is different because of the semantics of Cont
(the continuation monad): the result types of both the wrapped function and its functional argument must be the same, and so the transformer puts both into the inner monad. In general, there is no magic formula to create a transformer version of a monad; the form of each transformer depends on what makes sense in the context of its nontransformer type.
Lifting[edit]
The lift
function is critical in daytoday usage of transformers.
liftM[edit]
Let us begin by considering the more familiar liftM
function. It has the following type:
liftM :: Monad m => (a > b) > m a > m b
liftM
applies a function (a > b)
to a value within a monad m
. If you prefer the pointfree interpretation, it converts a regular function into one that acts within m
— that is what is meant by lifting.
To recapitulate, here is a simple example of liftM
usage. The following pieces of code all mean the same thing.
do notation  liftM  liftM as an operator 

do x < monadicValue return (f x) 
liftM f monadicValue 
f `liftM` monadicValue 
The third example, in which we use liftM
as an operator, suggests an interesting way of viewing liftM
: it is a monadic analogue of ($)
!
non monadic  monadic 

f $ value

f `liftM` monadicValue 
lift[edit]
When using combined monads created with monad transformers, we avoid having to manage the inner monad types explicitly, and our result is clearer, simpler code. Instead of creating additional doblocks within the computation to manipulate values in the inner monad type, we can use lifting operations to bring functions from the inner monad into the combined monad.
With liftM
we have seen how the essence of lifting is promoting something into a monad. The lift
function, which is available for all monad transformers, performs a different kind of lifting: it promotes a computation from the inner monad into the combined monad. lift
is defined as the single method of the MonadTrans
class in Control.Monad.Trans.Class.
class MonadTrans t where lift :: (Monad m) => m a > t m a
There is a variant of lift
specific to IO
operations, called liftIO
, which is the single method of the MonadIO
class in Control.Monad.IO.Class.
class (Monad m) => MonadIO m where liftIO :: IO a > m a
liftIO
can be convenient when multiple transformers are stacked into a single combined monad. In such cases, IO
is always the innermost monad, and so we typically need more than one lift to bring IO
values to the top of the stack. liftIO
is defined for the instances in a way that allows us to bring an IO
value from any depth while writing the function a single time.
Implementing lift
[edit]
Implementing lift
is usually pretty straightforward. Consider the transformer MaybeT
:
instance MonadTrans MaybeT where lift m = MaybeT (m >>= return . Just)
We begin with a monadic value of the inner monad (the middle layer of our monadic sandwich metaphor). Using the bind operator and a type constructor for the base monad, we slip the base monad (the bottom slice of our sandwich) underneath. Finally, we use the constructor MaybeT
(to place the top slice of our sandwich). Just as in the implementation of the Monad
class, both the bind operator and the generic return
are working within the boundaries of the inner monad.
Exercises 


Implementing transformers[edit]
In order to develop a better feel for the workings of transformers, we will discuss two more implementations in the standard libraries.
The List transformer[edit]
Just as with the Maybe
transformer, we start by creating a datatype with a constructor that takes one argument:
newtype ListT m a = ListT { runListT :: m [a] }
The implementation of the ListT m
monad is strikingly similar to the list monad itself. We do the same operations done for []
, but with a little extra support to operate within the inner monad m
, and to pack and unpack the monadic sandwich.
List  ListT 

instance Monad [] where return x = [x] xs >>= f = let yss = map f xs in concat yss 
instance (Monad m) => Monad (ListT m) where return x = ListT $ return [x] tm >>= f = ListT $ runListT tm >>= \xs > mapM (runListT . f) xs >>= \yss > return (concat yss) 
Exercises 


The State transformer[edit]
Previously, we pored over the implementation of one simple monad transformer, MaybeT
, and reviewed the implementation of another, ListT
, taking a detour along the way to talk about lifting from a monad into its transformer variant. Here, we will bring the two ideas together by taking a detailed look at the implementation of StateT
. You might want to review the section on the State monad before continuing.
Just as the State monad might have been built upon the definition newtype State s a = State { runState :: (s > (a,s)) }
^{[2]} the StateT transformer is built upon the definition
newtype StateT s m a = StateT { runStateT :: (s > m (a,s)) }
State s
is an instance of both the Monad
class and the MonadState s
class (which provides get
and put
), so StateT s m
should also be members of the Monad
and MonadState s
classes. Furthermore, if m
is an instance of MonadPlus
, StateT s m
should also be a member of MonadPlus
.
To define StateT s m
as a Monad
instance:
State  StateT 

newtype State s a = State { runState :: (s > (a,s)) } instance Monad (State s) where return a = State $ \s > (a,s) (State x) >>= f = State $ \s > let (v,s') = x s in runState (f v) s' 
newtype StateT s m a = StateT { runStateT :: (s > m (a,s)) } instance (Monad m) => Monad (StateT s m) where return a = StateT $ \s > return (a,s) (StateT x) >>= f = StateT $ \s > do (v,s') < x s  get new value and state runStateT (f v) s'  pass them to f 
Our definition of return
makes use of the return
function of the inner monad. The binding operator uses a doblock to perform a computation in the inner monad.
We also want to declare all combined monads that use the StateT
transformer to be instances of the MonadState
class, so we will have to give definitions for get
and put
:
instance (Monad m) => MonadState s (StateT s m) where get = StateT $ \s > return (s,s) put s = StateT $ \_ > return ((),s)
Finally, we want to declare all combined monads in which StateT
is used with an instance of MonadPlus
to be instances of MonadPlus
:
instance (MonadPlus m) => MonadPlus (StateT s m) where mzero = StateT $ \s > mzero (StateT x1) `mplus` (StateT x2) = StateT $ \s > (x1 s) `mplus` (x2 s)
The final step: make our monad transformer fully integrated with Haskell's monad classes by making StateT s
an instance of the MonadTrans
. So we need a lift
function:
instance MonadTrans (StateT s) where lift c = StateT $ \s > c >>= (\x > return (x,s))
The lift
function creates a StateT
state transformation function that binds the computation in the inner monad to a function that packages the result with the input state. If, for instance, we apply StateT to the List monad, a function that returns a list (i.e., a computation in the List monad) can be lifted into StateT s []
where it becomes a function that returns a StateT (s > [(a,s)])
. I.e. the lifted computation produces multiple (value,state) pairs from its input state. This "forks" the computation in StateT, creating a different branch of the computation for each value in the list returned by the lifted function. Of course, applying StateT
to a different monad will produce different semantics for the lift
function.
Acknowledgements[edit]
This module uses a number of excerpts from All About Monads, with permission from its author Jeff Newbern.
Notes
 ↑ The wrapping interpretation is only literally true for versions of the mtl package older than 2.0.0.0 .
 ↑ In the
transformers
andmtl
packages,State s
is implemented as a type synonym forStateT s Identity
. Incidentally, that explains why there was astate
function instead of theState
constructor back in the chapter aboutState
, and why we had to defer the explanation until now.