We’ve recently how the maybe monad has helped us avoid **triangle of doom** code patterns. Without it, we had to check each function call for success. However, the examples we looked at were all **pure code examples**. Consider this:

```
main :: IO
main = do
maybeUserName <- readUserName
case maybeUserName of
Nothing -> print “Invalid user name!”
Just (uName) -> do
maybeEmail <- readEmail
case maybeEmail of
Nothing -> print “Invalid email!”
Just (email) -> do
maybePassword <- readPassword
Case maybePassword of
Nothing -> print “Invalid Password”
Just password -> login uName email password
readUserName :: IO (Maybe String)
readUserName = do
str <- getLIne
if length str > 5
then return $ Just str
else return Nothing
readEmail :: IO (Maybe String)
...
readPassword :: IO (Maybe String)
...
login :: String -> String -> String -> IO ()
...
```

In this example, all our potentially problematic code takes place within the IO monad. How can we use the `Maybe`

monad when we’re **already in another monad**?

## Monad Transformers

Luckily, we can get the desired behavior by using **monad transformers** to **combine monads**. In this example, we’ll wrap the IO actions within a transformer called `MaybeT`

.

A monad transformer is fundamentally a **wrapper type**. It is generally parameterized by another monadic type. You can then run actions from the inner monad, while adding your own customized behavior for combining actions in this new monad. The common transformers add `T`

to the end of an existing monad. Here’s the definition of `MaybeT`

:

```
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
instance (Monad m) => Monad (MaybeT m) where
return = lift . return
x >>= f = MaybeT $ do
v <- runMaybeT x
case v of
Nothing -> return Nothing
Just y -> runMaybeT (f y)
```

So `MaybeT`

itself is simply a newtype. It in turn contains a wrapper around a `Maybe`

value. If the type `m`

is a monad, we can **also make a monad out of** `MaybeT`

.

Let’s consider our example. We want to use `MaybeT`

to wrap the `IO`

monad, so we can run IO actions. This means our new monad is `MaybeT IO`

. Our three helper functions all return strings, so they each get the type `MaybeT IO String`

.
To convert the old `IO`

code into the `MaybeT`

monad, all we need to do is wrap the `IO`

action in the `MaybeT`

constructor.

```
readUserName :: MaybeT IO String
readUserName = MaybeT $ do
str <- getLIne
if length str > 5
then return $ Just str
else return Nothing
readEmail :: MaybeT IO String
...
readPassword :: MaybeT IO String
...
```

Now we can wrap all three of these calls into a single monadic action, and do a **single pattern match** to get the results. We’ll use the `runMaybeT`

function to unwrap the `Maybe`

value from the `MaybeT`

:

```
main :: IO ()
main = do
maybeCreds <- runMaybeT $ do
usr <- readUserName
email <- readEmail
pass <- readPassword
return (usr, email, pass)
case maybeCreds of
Nothing -> print "Couldn't login!"
Just (u, e, p) -> login u e p
```

And this new code will have the proper short-circuiting behavior of the Maybe monad! If any of the read functions fail, our code will immediately return `Nothing`

.

## Adding More Layers

Here’s the best part about monad transformers. Since our newly created type is a monad itself, we can wrap it inside **another transformer**! Pretty much all common monads have transformer types in the same way the `MaybeT`

is a transformer for the ordinary `Maybe`

monad.

For a quick example, suppose we had an `Env`

type containing some user information. We could wrap this environment in a **Reader**. However, we want to still have access to `IO`

functionality, so we’ll use the `ReaderT`

transformer. Then we can wrap the result in `MaybeT`

transformer.

```
type Env = (Maybe String, Maybe String, Maybe String)
readUserName :: MaybeT (ReaderT Env IO) String
readUserName = MaybeT $ do
(maybeOldUser, _, _) <- ask
case maybeOldUser of
Just str -> return str
Nothing -> do
-- lift allows normal IO functions from inside ReaderT Env IO!
input <- lift getLine
if length input > 5
then return (Just input)
else return Nothing
```

Notice we had to use `lift`

to run the IO function `getLine`

. In a monad transformer, the lift function allows you to run actions in the underlying monad. So using `lift`

in the `ReaderT Env IO`

action allows `IO`

functions. Within a `MaybeT (ReaderT Env IO)`

function, calling `lift`

would allow you to run a `Reader`

function. We don’t need this above since the bulk of the code lies in `Reader`

actions wrapped by the `MaybeT`

constructor.

To understand the concept of lifting, think of your monad layer as a stack. When you have a `ReaderT Env IO`

action, imagine a `Reader Env`

monad on top of the `IO`

monad. An IO action exists on the bottom layer. So to run it from the upper layer, you need to **lift** it up. If your stack is more than two layers, you can lift **multiple times**. Calling `lift`

twice from the `MaybeT (ReaderT Env IO)`

monad will allow you to call `IO`

functions.

It’s inconvenient to have to know how many times to call lift to get to a particular level of the chain. Thus **helper functions** are frequently used for this. Additionally, since monad transformers can run several layers deep, the types can get complicated, so it is typical to use type synonyms liberally.

```
type TripleMonad a = MaybeT (ReaderT Env IO) a
performReader :: ReaderT Env IO a -> TripleMonad a
performReader = lift
performIO :: IO a -> TripleMonad a
performIO = lift . lift
```

## Typeclasses

As a similar idea, there are some typeclasses which allow you to make certain **assumptions about the monad stack** below. For instance, you often don’t care what the exact stack is, but you just need `IO`

to exist somewhere on the stack. This is the purpose of the `MonadIO`

typeclass:

```
class (Monad m) => MonadIO m where
liftIO :: IO a -> m a
```

We can use this behavior to get a function to print even when we don’t know its **exact monad**:

```
debugFunc :: (MonadIO m) => String -> m a
debugFunc input = do
liftIO $ print “Interpreting Input: “ ++ input
…
```

One final note: You **cannot**, in general, **wrap another monad** with the **IO monad** using a transformer. You can, however, make the other monadic value the return type of an IO action.

```
func :: IO (Maybe String)
-- This type makes sense
func2 :: IO_T (ReaderT Env (Maybe)) string
-- This does not exist
```

## Summary

Monad Transformers allow us to wrap monads within other monads. All of the basic built-in monads have transformer types. We name these types by adding `T`

to the end of the name, like `MaybeT`

. Monad transformers let us get useful behavior from all the different monads on our stack. The `lift`

function allows us to run functions within monads further down the stack.

Monad transformers are extremely important when trying to write meaningful Haskell code. If you want to get started with Haskell, be sure to check out our free checklist for Haskell tools.

Want to practice some Haskell skills, but aren’t ready for monads? You can also take a look at our recursion workbook (it’s also free!). It has two chapters of content on recursion and higher order functions, as well as 10 practice problems.

Stay tuned, because next week we will complete our discussion of our abstract wrapper types (functors, applicatives, monads) by exploring the laws governing their behavior.