# Monad and Monad Transformer Templates

This is just a quick reference for implementing monad and monad transform type class instances. Monad transformers in particular require a lot of boilerplate code. Monad transformers allow us to combine multiple monads like `Maybe`

, `Reader`

and `IO`

into a single monad stack and access the capabilities of each monad. A common stack is `ReaderT Env IO`

, where `Env`

may contain mutable references. This is generally recommended over using `WriterT`

and `StateT`

for performance and safety issues. You can read more about best practices in this FPComplete article: ReaderT Design Pattern.

## Monad Template

You should be generally familiar with how Functor, Applicative and Monad are defined in GHC. Here is a slightly redacted version.

```
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
-- | Lift a value.
pure :: a -> f a
-- | Sequential application.
(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id
-- | Lift a binary function to actions.
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)
-- | Sequence actions, discarding the value of the first argument.
(*>) :: f a -> f b -> f b
a1 *> a2 = (id <$ a1) <*> a2
-- | Sequence actions, discarding the value of the second argument.
(<*) :: f a -> f b -> f a
(<*) = liftA2 const
class Applicative m => Monad m where
-- | Sequentially compose two actions, passing any value produced
-- by the first as an argument to the second.
(>>=) :: forall a b. m a -> (a -> m b) -> m b
-- | Sequentially compose two actions, discarding any value produced
-- by the first, like sequencing operators (such as the semicolon)
-- in imperative languages.
(>>) :: forall a b. m a -> m b -> m b
m >> k = m >>= \_ -> k
-- | Inject a value into the monadic type.
return :: a -> m a
return = pure
-- | Fail with a message.
fail :: String -> m a
fail s = errorWithoutStackTrace s
join :: (Monad m) => m (m a) -> m a
join x = x >>= id
```

These are my one sentence motivations (not definitions) for using these type classes in Haskell:

Functor: apply a function to a value/values in a container without removing the container.

Applicative: build values from independent computations.

Monad: build values from interdependent computations.

Letâ€™s define our own type and instances for these three type classes. I use the naming scheme from OCaml `Option`

so we can compile and avoid name clashes with `Maybe`

.

```
import Control.Applicative (liftA2, Alternative(..))
import Control.Monad (liftM, ap, MonadPlus(..))
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.Trans.Class (MonadTrans(..), lift)
data Option a = None | Some a deriving (Eq, Ord, Show)
instance Functor Option where
fmap _ None = None
fmap f (Some a) = Some (f a)
instance Applicative Option where
pure = Some
Some f <*> m = fmap f m
None <*> _m = None
liftA2 f (Some x) (Some y) = Some (f x y)
liftA2 _ _ _ = None
Some _m1 *> m2 = m2
None *> _m2 = None
instance Monad Option where
(Some x) >>= k = k x
None >>= _ = None
(>>) = (*>)
fail _ = None
```

Here are some motivating functions for our Monad instance. We have three functions that we want to combine:

```
residentToAddress :: String -> Option String
residentToAddress "Foo" = Some "10 Downing Street"
residentToAddress "Bar" = Some "1600 Pennsylvania Ave NW"
residentToAddress _ = None
addressToPhoneNumber :: String -> Option String
addressToPhoneNumber "10 Downing Street" = Some "+44 20 7925 0918"
addressToPhoneNumber "1600 Pennsylvania Ave NW" = Some "+1 202-456-1111"
addressToPhoneNumber _ = None
phoneNumberToAccountNumber :: String -> Option String
phoneNumberToAccountNumber "+44 20 7925 0918" = Some "1111-1111-1111-1111"
phoneNumberToAccountNumber "+1 202-456-1111" = Some "2222-2222-2222-2222"
phoneNumberToAccountNumber _ = None
```

Without using monads it looks like this:

```
residentToAccountNumber :: String -> Option String
residentToAccountNumber r =
case residentToAddress r of
Some a ->
case addressToPhoneNumber a of
Some p -> phoneNumberToAccountNumber p
None -> None
None -> None
```

Using monads (particularly with do-syntax) we can simplify it:

```
residentToAccountNumberDoSyntaxSugar :: String -> Option String
residentToAccountNumberDoSyntaxSugar r = do
address <- residentToAddress r
phoneNumber <- addressToPhoneNumber address
residentToAccountNumber phoneNumber
residentToAccountNumberNoSyntaxSugar :: String -> Option String
residentToAccountNumberNoSyntaxSugar r =
residentToAddress r >>= \address -> addressToPhoneNumber address >>= \phoneNumber -> residentToAccountNumber phoneNumber
```

## Monad Transformer Template

```
newtype OptionT m a = OptionT { runOptionT :: m (Option a) }
mapOptionT :: (m (Option a) -> n (Option b)) -> OptionT m a -> OptionT n b
mapOptionT f = OptionT . f . runOptionT
instance (Functor m) => Functor (OptionT m) where
fmap f = mapOptionT (fmap (fmap f))
instance (Functor m, Monad m) => Applicative (OptionT m) where
pure = OptionT . pure . Some
mf <*> mx = OptionT $ do
mb_f <- runOptionT mf
case mb_f of
None -> pure None
Some f -> do
mb_x <- runOptionT mx
case mb_x of
None -> pure None
Some x -> pure (Some (f x))
m *> k = m >>= \_ -> k
instance (Monad m) => Monad (OptionT m) where
return = OptionT . pure . Some
x >>= f = OptionT $ do
v <- runOptionT x
case v of
None -> pure None
Some y -> runOptionT (f y)
fail _ = OptionT (pure None)
instance MonadTrans OptionT where
lift = OptionT . liftM Some
instance (MonadIO m) => MonadIO (OptionT m) where
liftIO = lift . liftIO
instance Monad m => Alternative (OptionT m) where
empty = OptionT $ pure None
x <|> y = OptionT $ do
ov <- runOptionT x
case ov of
None -> runOptionT y
Some _ -> pure ov
instance Monad m => MonadPlus (OptionT m) where
mzero = empty
mplus = (<|>)
residentToAddressMT :: IO () -> String -> OptionT IO String
residentToAddressMT action "Foo" = do liftIO action; OptionT . pure $ Some "10 Downing Street"
residentToAddressMT action "Bar" = do liftIO action; OptionT . pure $ Some "1600 Pennsylvania Ave NW"
residentToAddressMT action _ = do liftIO action; OptionT . pure $ None
residentToAccountNumberMonadTransformer :: (OptionT IO String)
residentToAccountNumberMonadTransformer = do
r <- liftIO getLine
_a <- residentToAddressMT (print "printing from residentToAddressMT") r
-- you can wrap pure Maybe Monad
OptionT . pure $ do
address <- residentToAddress r
phoneNumber <- addressToPhoneNumber address
phoneNumberToAccountNumber phoneNumber
main :: IO ()
main = do
oaccount <- runOptionT residentToAccountNumberMonadTransformer
print oaccount
```