# Monad transformers

## Motivation

• Programs often perform several side-effects

• Error reporting
• Stateful computations
• I/O
• So, you can imagine a super-monad that does all of that

• What happens if I need a monad with less effects?

• Redefine that definition for `m a`, adapt `return` and `(>>=)` as well as the non-proper morphisms.
• What happens if I need a monad with more effects?

• Redefine that definition for `m a`, adapt `return` and `(>>=)` as well as the non-proper morphisms.
• We want to compose effects in a modular manner.

We would like non-proper morphisms, `return`, and `(>>=)` require minimum modifications when effects are added/removed.

• Monad transformers help us to do that

It allows us to combine effects on demand!
Not all the possible combinations of effects can be modularly combined!

Monad transformers are not the perfect solution, but they certainly helps (we will discuss more of the consequences of combining effects in the next lecture).

## Running example: a simple interpreter

• During this lecture, we consider a simple monadic interpreter.

• The interpreter underlying monad is going to be modularly enhanced with different effects.

• A simple (non-monadic) interpreter of expressions

```data Expr =   Lit Integer
| Expr :+: Expr

s_eval :: Expr -> Integer
s_eval (Lit n)     = n
s_eval (e1 :+: e2) = s_eval e1 :+: s_eval e2 ```

This code is not monadic, but we can change that.

## Interpreter0: no side-effects

code

• Any code can be "lifted" into the identity monad, i.e., a monad with no side-effects.

```import Control.Monad.Identity
type Eval a = Identity a
```

Type `Eval a` denotes a monadic computation.

• We change the type of the interpreter to return a monadic computation

``` eval :: Expr  -> Eval Integer
eval (Lit n)    = return n
eval (a :+: b)  = (+) <\$> (eval a) <*> (eval b) ```

We leverage the function `runIdentity :: Identity a -> a` to run the interpreter.

``` runEval :: Eval a -> a
runEval = CMI.runIdentity ```

There are no effects, it just computes the result. More formally, we have that

` runEval . eval  ≡ s_eval  `
• We want to extend our interpreter with new features

• Local declarations
• Exceptions
• References
• How are we going to extend the `Eval` monad?

## Enter monad transformers

• Monad transformers are type-level functions

• A certain monad transformer `T` takes a monad `m` and produces a monad with additional side-effects

• Every monad transformer `T` maps monads into a set of monads with the side-effects added by `T`

## Interpreter1: the reader monad transformer

code

• We want to extend our language of expression with local bindings, e.g., we would like to run a program like `let x = 5; x+x`

• We extend our data type for expressions

```data Expr = Lit Integer
| Expr :+: Expr
| Var Name            -- new
| Let Name Expr Expr  -- new ```
• Bindings are immutable, i.e., once a variable is bound to a value, it cannot be changed

• Expression can now involve bound variables, e.g., `x+y`.

• To evaluate expressions, `eval` should include an immutable environment which contains the values for bound variables.

• We model environments as mappings from variables names to values, i.e., think it a mapping as an element of type `[(Name, Value)]` or `Name -> Maybe Value`.

We use mappings from the module `Data.Map`

``` type Env = Map Name Value

emptyEnv = Map.empty
Map.lookup :: Ord k => k -> Map k a -> Maybe a
Map.insert :: Ord k => k -> a -> Map k a -> Map k a ```
• We would like to implement a monad with a read-only environment since bindings are immutable

• One alternative is to hard-wire it into the interpreter

`eval :: Env -> Expr -> Eval Value `

This means that there would be some plumbing to pass the environment between recursive calls (recall lecture 3).

• Instead, we use the monad transformer `ReaderT` to add a read-only state into the `Eval` monad!

In other words, `ReaderT` takes a monad `m` and returns a monad which support two operations: `local` and `ask` — such monads are called `MonadReader`.

A monad obtained by the transformer `ReaderT` is a `MonadReader`, but not all `MonadReader`s are obtained by using the monad transformer `ReaderT`!
``` data ReaderT s m a

runReaderT :: ReaderT s m a -> (s -> m a)

local      :: MonadReader s m => (s -> s) -> m a -> m a
ask        :: MonadReader s m => m s ```
• The monad `Eval` is then responsible for the plumbing required to pass around the environment.

``` newtype Eval a = MkEval (ReaderT Env (Identity) a)
deriving (Functor, Applicative, Monad, MonadReader Env) ```

We introduce a new data type, rather than just a type synonym, because we want Haskell to derive some type-classes instances.

Due to deriving `MonadReader Env`, our evaluation monad supports

``` local :: MonadReader Env Identity => (Env -> Env) -> Identity a -> Identity a
ask   :: MonadReader Env Identity => Identity Env ```
• Let us define some environment manipulation based on `local` and `ask`.

Looking up the value of a variable in the enviroment.

``` lookupVar :: Name -> Eval Value
lookupVar x = do
env <- ask
case Map.lookup x env of
Nothing -> fail \$ "Variable " ++ x ++ " not found."
Just v  -> return v ```

We can extend the environment with a new binding for a local computation. Since we are using a reader monad, we can be sure that this binding does not escape outside its intended scope.

``` localScope :: Name -> Value -> Eval a -> Eval a
localScope n v = local (Map.insert n v) ```
• The interpreter is extended by simply adding cases for the two new constructs. (None of the old cases has to be changed.)

``` eval :: Expr -> Eval Value
eval (Lit n)       = return n
eval (a :+: b)     = (+) <\$> eval a <*> eval b
eval (Var n)       = lookupVar n                 -- here, we use ask
eval (Let n e1 e2) = do v <- eval e1
localScope n v (eval e2) -- here, we use local ```
• The `run` function simply runs the interpreter with the initial empty environment.

``` runEval :: Eval a -> a
runEval (MkEval reader) = runIdentity (runReaderT reader emptyEnv) ```

Observe how we run the reader monad first, and then the identity monad.

When using monad transformers, you start running the outermost monad and finish with the innermost one of your monad stack.

• Example

```runEval \$ eval (parse "let x=1+2; x+x")
> 6 ```

## Interpreter 2: the state monad transformer

code

• We want to extend our language of expression with mutable references, e.g., we would like to run a program like `let r = new 7; !r+!r`

• We add new constructors in our expressions language for creation, reading, and writing of references.

```data Expr = Lit Integer
| Expr :+: Expr
| Var Name
| Let Name Expr Expr
| NewRef Expr         -- new
| Deref Expr          -- new
| Expr := Expr        -- new ```

Expression `NewRef e` creates a fresh reference which initially contains the value denoted by `e`.

Expression `Deref e` denotes the value stored by the reference denoted by `e`.

Expression `e1 := e2` changes the value stored in the reference denoted by `e1` with the value denoted by `e2`.

• The interpreter needs a notion of memory or store to keep the values stored in references

• This store is mutable, since references are mutable too!

• We represent it as a mapping from memory locations to values

``` type Ptr   = Value
data Store = Store { nextPtr :: Ptr
, heap    :: Map Ptr Value
} ```

A `Store` is then a mapping from a value denoting a memory location to the value stored at that location.

For instance, the following mapping

`  Map.insert 2 42 (Map.insert 1 7 (Map.insert 0 101 Map.empty)) `

denotes a memory with three references: at location `0` with value `101`, at location `1` with value `7`, and at location `2` with value `42`.

We also remember the next unused pointer as part of the store (useful when allocating a new reference).

``` emptyStore :: Store
emptyStore = Store 0 Map.empty ```
• As before, one alternative is to hard-wire it into the interpreter

`eval :: Store -> Expr -> Eval Value `

This means that there would be some plumbing to pass the store (memory) between recursive calls (recall lecture 3).

• Instead, we use the monad transformer `StateT` to add a mutable state into the `Eval` monad!

In other words, `StateT` takes a monad `m` and returns a monad which contains a mutable state of certain type `s` and two operations: `get` and `put` — such monads are called `MonadState s`. (Actually, they have one more operation (`state`) but we will not describe it here)

``` data StateT s m a

evalStateT :: Monad m => StateT s m a -> s -> m a

get        :: MonadState s m => m s
put        :: MonadState s m => s -> m () ```
• The monad `Eval` is then responsible for the plumbing required to pass around the store.

``` newtype Eval a = MkEval (StateT Store (ReaderT Env Identity) a)
deriving (Functor, Applicative,
Monad, MonadState Store, MonadReader Env) ```
• Alternatively, we could have defined an state-reader monad from scratch, i.e., not using the monad transformers

`data Eval a = MkEval (\Store -> Env -> (a, Store)) `
Exercise: Implement a "state-reader monad" directly
``` newtype MyMonad s e a = MyMonad {runMyMonad :: s -> e -> (a,s)}

instance Monad (MyMonad s e) where
return = returnMyMonad
(>>=)  = bindMyMonad

returnMyMonad :: a -> MyMonad s e a
returnMyMonad x = MyMonad \$ \s -> \ e -> (x, s) ```

While it works, the price to pay is modularity.

• Let us define some operations for the interpreter based on `get` and `put`

Creation of a new reference: modify both the next available memory location and the heap.

``` newRef :: Value -> Eval Ptr
newRef v = do store <- get
let ptr      = nextPtr store
new_ptr  = 1 + ptr
newHeap  = Map.insert ptr v (heap store)
put (Store new_ptr newHeap)
return ptr ```

Getting the value of a reference: look up a memory location in the store. We crash with our own "segfault" if given a non-existing pointer (observe that the state has not been changed.)

``` deref :: Ptr -> Eval Value
deref p = do st <- get
let h = heap st
case Map.lookup p h of
Nothing -> fail ("Segmentation fault: "++show p++" is not bound")
Just v  -> return v ```

Updating a reference: change a value in the store.

```  (=:) :: MonadState Store m => Ptr -> Value -> m Value
p =: v = do store <- get
let updt_heap = Map.adjust (const v) p (heap store)
put (store {heap = updt_heap})
return v
-- Map.adjust :: (Ord k) => (a -> a) -> k -> Map k a -> Map k a ```

Observe that `(=:)` has no effect if the reference does not exist.

Exercise: Maybe that is not the best semantics. What would it be a better one?
• We define the evaluation of expressions for the new cases with the functions described above.

``` eval :: Expr -> Eval Value
eval (Lit n)       = return n
eval (a :+: b)     = (+) <\$> eval a <*> eval b
eval (Var x)       = lookupVar x
eval (Let n e1 e2) = do v <- eval e1
localScope n v (eval e2)
eval (NewRef e)    = do v <- eval e
newRef v
eval (Deref e)     = do r <- eval e
deref r
eval (pe := ve)    = do p <- eval pe
v <- eval ve
p =: v ```

As before, we do not need to change the definition for the old constructors.

• We can test it

```> runEval \$ eval \$ parse "let p=new 7; !p"
7 ```
• Unfortunately, our expression language supports pointer arithmetic (like C), so a pointer might dereference another one — a recipe for disaster!

```> runEval \$ eval \$ parse "let p=new 1; let q=new 1738; !(p+1)"
1738 ```
• How are we going to fix it?

• Restricting the grammar, i.e., `!` only accepts variables names (not expressions)
• Small type-system (overkill here)
• What else can go wrong with our interpreter?

Expressions might refer to unbound variables / references.

```> runEval \$ eval \$ parse "q + 1"
*** Exception: Variable q not found. ```
```> runEval \$ eval \$ parse "!q"
*** Exception: Variable q not found. ```

We need some exception handling mechanism into the language of expressions.

## Summary

• Programs often handle more than one effect

• Monad transformer are type-level functions which allow one to extend existing monads with additional side-effects

• The deriving mechanisms in Haskell is quite powerful and promote re-utilization of code

• Monad transformers are not essential and you can create your own monad with all the effects that you need. The problem? Modularity, i.e., code rewritten if you need to change your monad to add a new effect.