11 Jan

# Monads

Read *“You Could Have Invented Monads! (And Maybe You Already Have)”* from the exercises sheet and follow along.

This time, no new examples will be provided, only additional explanations and tips for solving the exercises in the sheet.

## Audit

Function that also **logs** something, aside from returning its value.

### 1 bind

You can think of `bind f`

as an “upgraded” `f`

, and just write what it does with its argument: `(prevRes, prevLog)`

.

Some examples of logging functions:

```
add5 :: Float -> (Float, String)
add5 x = (x + 5, "add5 was called")
divideBy2 :: Float -> Audit Float -- same as (Float, String)
divideBy2 x = (x / 2, "divideBy2 was called")
```

```
> add5 10
(15, "add5 was called")
```

Composing them using the `bind`

function:

```
divideThenAdd :: Float -> (Float, String)
divideThenAdd = (bind add5) . divideBy2
```

```
> divideThenAdd 20
15 -- 20/2=10 +5=15
```

Using the composition operator `#`

:

```
divideThenAdd :: Float -> (Float, String)
divideThenAdd = add5 # divideBy2
```

### 2 unit

Remember that `lift f`

is a function, so it may be easier to understand if it is written like this:

```
lift :: (a -> b) -> (a -> Audit b)
(lift f) x = unit (f x)
```

Or even:

```
(lift f) x = (f(x), "")
```

Which explains what the *lifted* `f`

does to its argument, `f`

: it creates a pair of the normal result `f(x)`

and logs nothing (`""`

).

## Nondet

Function that returns **multiple** values of the same type – like a list.

### 4 bind

Again, remember to treat `bind f`

as a function. It may also be useful to remember what the built-in function `concat`

does.

Some example non-deterministic functions:

```
oppositeToo :: Int -> [Int]
oppositeToo x = [x, -x]
plus1n2n3 :: Int -> Nondet Int -- same as [Int]
plus1n2n3 x = [x + 1, x + 2, x + 3]
```

```
> oppositeToo 5
[5, -5]
> plus1n2n3 10
[11, 12, 13]
```

Composing them:

```
plusOpposites :: Int -> [Int]
plusOpposites = oppositeToo # plus1n2n3
-- or explicitly with the `bind` function: (bind oppositeToo) . plus1n2n3
```

```
> plusOpposites 10
[11,-11, 12,-12, 13,-13]
```

### 5 unit

Just like before, keep in mind that `lift f`

should be treated like a function:

```
lift :: (a -> b) -> (a -> Nondet b)
(lift f) x = [f(x)]
```

## Randomized

Function that uses **randomization** in its body, which requires a seed (for generating random numbers).

To avoid getting tangled in notation, it may be useful to remember that `StdGen`

can be thought of as a `Seed`

. Also `MyRandom a`

describes a function that returns an element of type `a`

and employs an element of randomness in its body (also returning a new `Seed`

).

```
type Seed = StdGen -- alias
type RandFunc a = Seed -> (a,Seed) -- instead of MyRandom a
```

If you try to evaluate `uniformNat`

on, say `5`

, instead of getting a random integer between `0`

and `5`

you will get an error:

```
> uniformNat 5
error:
• "No instance for (Show (RandFunc Int))" -- says it can't print a function
• "Maybe you haven't applied a function to enough arguments?" -- good question
```

Let’s see what `uniformNat 5`

actually is:

```
> :type (uniformNat 5)
(uniformNat 5) :: RandFunc Int
```

It is a function that returns an integer (and uses some kind of randomness inside)! Of course we can’t print it.

In order to get a result, we also have to pass a `Seed`

to it. Luckily we have a seed defined for us - `zeroSeed`

:

```
> (uniformNat 5) zeroSeed
(1, 13463877652103410263) -- the generated integer is 1, the new seed is the long number
```