# Introduction to Monads

## Announcements

- HW 3 available on the course website.
- Contact us if you can't see your grades online.
- Use Piazza

```
{-# LANGUAGE NoImplicitPrelude, KindSignatures #-}
module Monads where
import Prelude hiding (filter)
import Data.Char (toUpper)
```

`import Control.Monad (liftM, liftM2, guard)`

## Quiz

Consider the definition of trees with values at their *leaves*.

```
data Tree a = Leaf a | Branch (Tree a) (Tree a)
deriving (Eq, Show)
```

Define the following function that combines together the data stored in the tree.

```
-- | zip two trees together
zipTree :: Tree a -> Tree b -> Tree (a,b)
zipTree = undefined
```

```
o o o
/ \ / \ / \
"a" o ===> 0 o ===> ("a",0) o
/ \ / \ / \
"b" "c" 1 2 ("b",1) ("c", 2)
```

```
testZip :: Bool
testZip =
zipTree (Branch (Leaf "a") (Branch (Leaf "b") (Leaf "c")))
(Branch (Leaf 0 ) (Branch (Leaf 1 ) (Leaf 2 )))
==
(Branch (Leaf ("a",0)) (Branch (Leaf ("b",1)) (Leaf ("c",2))))
```

Bonus points for defining this function in terms of a fold.

```
t :: Tree String
t = Branch (Leaf "a")
(Branch (Leaf "b")
(Leaf "c"))
```

# Programming With Effects

## Shall we be pure or impure?

The functional programming community divides into two camps:

"Pure" languages, such as Haskell, are based directly upon the mathematical notion of a function as a mapping from arguments to results.

"Impure" languages, such as ML, are based upon the extension of this notion with a range of possible effects, such as exceptions and assignments.

Pure languages are easier to reason about and may benefit from lazy evaluation, while impure languages may be more efficient and can lead to shorter programs.

One of the primary developments in the programming language community in recent years (starting in the early 1990s) has been an approach to integrating the pure and impure camps, based upon the notion of a "monad". This lecture introduces the use of monads for programming with effects in Haskell. However, although monads integrate "impure" programming into Haskell, they are more general than that.

# Abstracting programming patterns

Monads are an example of the idea of abstracting out a common programming pattern as a definition. Before considering monads, let us review this idea, by thinking about error recovery.

How could we define zipTree so that we can recover from failure?

```
zipTree1 :: Tree a -> Tree b -> Maybe (Tree (a,b))
zipTree1 (Leaf a) (Leaf b) =
Just (Leaf (a,b))
zipTree1 (Branch l r) (Branch l' r') = undefined
zipTree1 _ _ = Nothing
```

Yuck!

Do we need to use effects to write modular code???

## Look closely at the program

```
zipTree :: Tree a -> Tree b -> Maybe (Tree (a,b))
zipTree (Leaf a) (Leaf b) =
Just (Leaf (a,b)) <-------------------- this is how we
zipTree (Branch l r) (Branch l' r') = return a value
~~~~~~~~~~~~~~~~~~~~~~ |
case zipTree l l' of |
Nothing -> Nothing |
Just l'' -> <------- This is how we |
~~~~~~~~~~~~~~~~~~~~ use a value |
case zipTree r r' of | |
Nothing -> Nothing <-----| |
Just r'' -> |
~~~~~~~~~~~~~~~~~~~~~~~ |
Just (Branch l'' r'') <------------------|
zipTree _ _ = Nothing
```

## Common parts of the definition

For returning a value we have:

Just (Leaf(a,b)) Just x

General pattern:

` Just x `

Give the pattern a good name:

```
return :: a -> Maybe a
return x = Just x
```

For using a value we have:

case zipTree l l' of

Nothing -> Nothing Just l'' -> ... do something with l''case zipTree r r' of

Nothing -> Nothing Just r'' -> ... do something with r''

General pattern:

```
case x of
Nothing -> Nothing
Just y -> f y
```

Name that pattern ("bind") or ("use x in f"):

```
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
x >>= f =
case x of
Nothing -> Nothing
Just y -> f y
```

That is, the first argument is `Nothing`

then the second argument is ignored and `Nothing`

is returned as the result. Otherwise, if the first argument is of the form `Just x`

, then the second argument is applied to `x`

to give a result of type `Maybe b`

.

## Refactor the code!

Use the new general definitions to refactor the code.

```
zipTree2 :: Tree a -> Tree b -> Maybe (Tree (a,b))
zipTree2 (Leaf a) (Leaf b) = undefined
zipTree2 (Branch l r) (Branch l' r') = undefined
zipTree2 _ _ = Nothing
```

## Do notation

Haskell provides a special notation for expressions of the above structure, allowing them to be written in a more appealing form:

```
do x1 <- m1
x2 <- m2
...
xn <- mn
f x1 x2 ... xn
```

Hence, for example, our evaluator can be redefined as:

```
zipTree3 :: Tree a -> Tree b -> Maybe (Tree (a,b))
zipTree3 (Leaf a) (Leaf b) = do
return (Leaf (a,b))
zipTree3 (Branch l r) (Branch l' r') = do
l'' <- zipTree3 l l';
r'' <- zipTree3 r r';
return (Branch l'' r'')
zipTree3 _ _ = Nothing
```

# Monads in Haskell

The `do`

notation for sequencing is not specific to the `Maybe`

type, but can be used with any type that forms a *monad*. The general concept comes from a branch of mathematics called category theory. In Haskell, however, a monad is simply a parameterised type `m`

, together with two functions of the following types:

```
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
```

(*Aside*: the two functions are also required to satisfy some simple properties, but we will return to these later.) For example, if we take `m`

as the parameterised type `Maybe`

, `return`

as the function `Just :: a -> Maybe a`

, and `>>=`

as defined in the previous section, then we obtain our first example, called the *maybe monad*.

In fact, we can capture the notion of a monad as a new class declaration. In Haskell, a class is a collection of types that support certain overloaded functions. For example, the class `Eq`

of equality types can be declared as follows:

```
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
x /= y = not (x == y)
```

The declaration states that for a type `a`

to be an instance of the class `Eq`

, it must support equality and inequality operators of the specified types. In fact, because a default definition has already been included for `/=`

, declaring an instance of this class only requires a definition for `==`

. For example, the type `Bool`

can be made into an equality type as follows:

```
instance Eq Bool where
False == False = True
True == True = True
_ == _ = False
```

The notion of a monad can now be captured as follows:

```
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
```

That is, a monad is a parameterised type `m`

that supports `return`

and `>>=`

functions of the specified types. The fact that `m`

must be a parameterised type, rather than just a type, is inferred from its use in the types for the two functions. Using this declaration, it is now straightforward to make `Maybe`

into a monadic type:

```
instance Monad Maybe where
-- return :: a -> Maybe a
return x = Just x
-- (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing
(Just x) >>= f = f x
```

(*Aside*: types are not permitted in instance declarations, but we include them as comments for reference.) It is because of this declaration that the `do`

notation can be used to sequence `Maybe`

values. More generally, Haskell supports the use of this notation with any monadic type. In the next few sections we give some further examples of types that are monadic, and the benefits that result from recognising and exploiting this fact.

# The List Monad

The `Maybe`

monad provides a simple model of computations that can fail, in the sense that a value of type `Maybe a`

is either `Nothing`

, which we can think of as representing failure, or has the form `Just x`

for some `x`

of type `a`

, which we can think of as success.

The list monad generalises this notion, by permitting multiple results in the case of success. More precisely, a value of `[a]`

is either the empty list `[]`

, which we can think of as failure, or has the form of a non-empty list `[x1,x2,...,xn]`

for some `xi`

of type `a`

, which we can think of as success.

## A challenge

Write the function that considers each possible value `x`

from the list `xs`

, and each value `y`

from the list `ys`

, and return the pair `(x,y)`

.

```
pairs :: [Int] -> [Int] -> [(Int,Int)]
pairs xs ys = undefined
```

`testPairs = pairs [1,2,3,4] [5,6,7,8]`

Can we divide this up? What are the patterns here?

We have

concatMap (-> do something with x) xs

concatMap (-> do something with y) ys

Generalize to

concatMap f xs

Rejigger a bit to match the pattern above

(>>=) :: [a] -> (a -> [b]) -> [b] xs >>= f = concatMap f xs

What could return be?

return :: a -> [a] return x = [x]

Rewrite using >>= and return

```
pairs1 :: [Int] -> [Int] -> [(Int,Int)]
pairs1 xs ys = undefined
```

Rewrite using do notation

```
pairs2 :: [Int] -> [Int] -> [(Int,Int)]
pairs2 xs ys = undefined
```

`testPairs2 = pairs1 [1,2,3,4] [5,6,7,8]`

Making lists into a monadic type is straightforward:

```
instance Monad [] where
-- return :: a -> [a]
return x = [x]
-- (>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= f = concatMap f xs
```

(*Aside*: in this context, `[]`

denotes the list type `[a]`

without its parameter.) That is, return simply converts a value into a successful result containing that value, while `>>=`

provides a means of sequencing computations that may produce multiple results: `xs >>= f`

applies the function f to each of the results in the list xs to give a nested list of results, which is then concatenated to give a single list of results.

As a simple example of the use of the list monad, a function that returns all possible ways of pairing elements from two lists can be defined using the do notation as follows:

## List comprehensions

Recall the pairing function defined with the do notation

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.{haskell} pairs2 :: [Int] -> [Int] -> [(Int,Int)] pairs2 xs ys = do x <- xs y <- ys return (x, y) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It is interesting to note the similarity to how this function would be defined using the list comprehension notation:

`pairs3 xs ys = [ (x,y) | x <- xs, y <- ys ]`

What are some other examples that can be written using list comprehension?

- Rewrite the
`map`

function using a list comprehension.

`map' f xs = undefined`

- Create a list of all pairs where the first component is less than the second.

`pairs4 xs ys = undefined`

alternatively

```
pairs4' xs ys = do x <- xs
y <- ys
if (x < y) then [ (x,y) ] else []
```

alternatively

```
pairs4'' xs ys = do x <- xs
y <- ys
guard (x < y)
return (x,y)
```

- Rewrite
`filter`

, using a guarded list comprehension.

```
filter :: (a -> Bool) -> [a] -> [a]
filter f xs = undefined
```

- Remember quicksort?

```
quicksort [] = []
quicksort (x:xs) = quicksort xs1 ++ [x] ++ quicksort xs2 where
xs1 = [ y | y <- xs , y < x ]
xs2 = [ y | y <- xs , y >= x ]
```

In fact, there is a formal connection between the `do`

notation and the comprehension notation. Both are simply different shorthands for repeated use of the `>>=`

operator for lists. Indeed, the language *Gofer* that was one of the precursors to Haskell permitted the comprehension notation to be used with *any* monad. For simplicity however, Haskell only allows the comprehension notation to be used with lists.

## Credit

This lecture draws on lecture notes by Graham Hutton and John Hughes.

## News :

Welcome to CIS 552!

See the home page for basic
information about the course, the schedule for the lecture notes
and assignments, the resources for links to the required software
and online references, and the syllabus for detailed information about
the course policies.