# Introduction to Monads

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

## Announcements

HW 2 due Sunday, group coordination?

cabal install hlint

Course staff away all next week (ICFP). Stephanie gone until Oct 2.

## 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 (Leaf x) (Leaf y) = Leaf (x,y)
zipTree (Branch l1 r1) (Branch l2 r2) = Branch (zipTree l1 l2) (zipTree r1 r2)
zipTree _ _ = error "structures don't match"
```

```
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))))
```

# 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 *much* 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)) ---- returning an answer
zipTree1 (Branch l r) (Branch l' r') =
case (zipTree1 l l') of
Just l'' ->
case (zipTree1 r r') of
Just r'' ->
Just (Branch l'' r'') --- returning an answer
Nothing -> Nothing
Nothing -> Nothing
zipTree1 _ _ = Nothing
```

something >>= ('' -> somehow)

case something of Just r'' -> use r'' somehow Nothing -> Nothing

Yuck! Can we do better? You bet!

## 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
```

Abstract to 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) = return (Leaf (a,b))
zipTree2 (Branch l r) (Branch l' r') =
(zipTree2 l l') >>= (\l'' ->
(zipTree2 r r') >>= (\r'' ->
return (Branch l'' r'')))
zipTree2 _ _ = Nothing
```

```
zipTree3 :: Tree a -> Tree b -> Maybe (Tree (a,b))
zipTree3 (Leaf a) (Leaf b) = 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
```

## 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 function can be redefined as:

```
zipTree3 :: Tree a -> Tree b -> Maybe (Tree (a,b))
zipTree3 (Leaf a) (Leaf b) = undefined
zipTree3 (Branch l r) (Branch l' r') = undefined
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*. In otherwords, any type that is an instance of the `Monad`

type class. 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.

# Unpacking the do notation

So what does the Monad type class have to do with the `do`

notation? Well, remember code that we so nicely wrote in this form:

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

Haskell automagically translated that code into the following sequence of nested binds.

```
m1 >>= (\x1 ->
m2 >>= (\x2 ->
...
mn >>= (\xn ->
f x1 x2 ... xn)...))
```

So much easier to read with the arrows flipped around, no?

But wait, there's more. Sometimes with do notation, we get a line in the middle that *doesn't* bind a variable.

```
main = do
x <- doSomething
doSomethingElse -- what is going on here?
y <- andSoOn
f x y
```

In fact, we saw this sort of thing when using the `IO`

monad. (Yep, the IO type constructor is an instance of the `Monad`

type class. That means that under the covers, it is all binds and return.)

```
main :: IO ()
main = do
putStrLn "This is the Classes lecture. What is your name?"
inpStr <- getLine
putStrLn $ "Welcome to Haskell, " ++ inpStr ++ "!"
return ()
```

Sometimes we don't need to use the result of a computation (for example, if it has type `IO ()`

). However, we would still like to use bind for it's sequencing capabilities.... Surely printing the question should come before reading the answer, but in a lazy language it can be difficult to control what gets evaluated when.

That brings us to a derived monad operator, called sequence.

```
(>>) :: Monad m => m a -> m b -> m b
m1 >> m2 = undefined
```

```
whatDoesThisDo :: IO ()
whatDoesThisDo = foldr (>>) (putStrLn " Batman!")
(replicate 10 (putStr (show (0.0/0.0))))
```

Lines that aren't bind, are glued together with `>>`

.

```
doSomething >>= ( \x ->
doSomethingElse >> -- it was just a sequence
(andSoOn >>= ( \y ->
f x y)))
```

# 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 = pairs1 [1,2,3,4] [5,6,7,8]`

` [ (1,5),(1,6), (1,7),(1,8), (2,5),..`

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

We have

```
concatMap (\x -> do something with x) xs
concatMap (\y -> 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
```

Make sure that it still works.

`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

```
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, using do notation

`pairs4' xs ys = undefined`

alternatively, using `guard`

(which requires a bit more from the monad)

```
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) = undefined
```

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.