# Programming with Effects III

```
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_GHC -fno-warn-unused-matches #-}
module Monads3 where
import Prelude hiding (getLine, putStrLn, sequence, (>>), getLine)
```

Announcements: * HW 3 due Wednesday * RAE's extra office hours: Tuesday 2:30-4:30 near Levine 5th floor elevators * ASZ's extra office hours right after class * HW 2 discussion Wednesday

# List comprehension examples

Useful for testing:

```
testList :: [Int]
testList = [1..10]
```

Using list comprehensions...

- ... write a function to filter an input list, keeping only odd numbers:

```
odds :: [Int] -> [Int]
odds xs = [ x | x <- xs, odd x ]
```

- ... write a function to take the Cartesian product of the input list:

```
cartesianProduct :: [a] -> [(a,a)]
cartesianProduct xs = [ (x, y) | x <- xs, y <- xs ]
```

- ... write a function to multiply together all pairs of numbers in a list:

```
multPair :: [(Int,Int)] -> [Int]
multPair pairs = [ x * y | (x,y) <- pairs ]
```

- ... write a function to filter a list of strings, retaining only the palindromes:

```
palindromes :: [String] -> [String]
palindromes strs = [ x | x <- strs, reverse x == x ]
```

# Random Numbers

See RandomGen

# The IO Monad

Recall that interactive programs in Haskell are written using the type `IO a`

of "actions" that return a result of type `a`

, but may also perform some input/output. A number of primitives are provided for building values of this type, including:

```
return :: a -> IO a
(>>=) :: IO a -> (a -> IO b) -> IO b
getChar :: IO Char
putChar :: Char -> IO ()
```

The use of return and `>>=`

means that `IO`

is monadic, and hence that the do notation can be used to write interactive programs. For example, the action that reads a string of characters from the keyboard can be defined as follows:

```
getLine :: IO String
getLine = getChar >>= (\c ->
if c == '\n' then return []
else getLine >>= (\cs -> return (c:cs)))
```

It is interesting to note that the `IO`

monad can be viewed as a special case of the state monad, in which the internal state is a suitable representation of the "state of the world":

```
type World = ...
type IO a = World -> (a,World)
```

That is, an action can be viewed as a function that takes the current state of the world as its argument, and produces a value and a modified world as its result, in which the modified world reflects any input/output performed by the action. In reality, Haskell systems such as Hugs and GHC implement actions in a more efficient manner, but for the purposes of understanding the behavior of actions, the above interpretation can be useful.

# Arbitrary monads

An important benefit of abstracting out the notion of a monad into a single typeclass, is that it then becomes possible to define a number of useful functions that work in an arbitrary monad.

We've already seen this in the `pairs`

function

```
pairs xs ys = do
x <- xs
y <- ys
return (x, y)
```

What do you think the type of the above is ? (I left out an annotation deliberately!)

`ghci> :type pairs`

It takes two monadic values and returns a single *paired* monadic value. Be careful though! The function above will behave differently depending on what specific monad instance it is used with! If you use the `Maybe`

monad

```
ghci> pairs (Nothing) (Just 'a')
ghci> pairs (Just 42) (Nothing)
ghci> pairs (Just 2) (Just 'a')
```

this generalizes to the list monad

```
ghci> pairs [] ['a']
ghci> pairs [42] []
ghci> pairs [2] ['a']
ghci> pairs [1,2] "ab"
```

However, the behavior is quite different with the `IO`

monad

`ghci> pairs getChar getChar`

Other common generic operations can be adapted for monadic programming. For example, the `map`

function on lists can be generalized as follows:

```
liftM :: Monad m => (a -> b) -> m a -> m b
liftM f ma = ma >>= return . f
-- (>>=) :: Monad m => m a -> (a -> m b) -> m b
```

The `replicate`

function can also be generalized to work with monads:

```
replicateM :: Monad m => Int -> m a -> m [a]
replicateM n ma = ma >>= return . replicate n
replicateM' n ma = do a <- ma
return (replicate n a)
```

```
replicateM'' n ma = do a <- ma
return $ a : replicateM'' (n-1) ma
```

As a final example, we can define a function that transforms a list of monadic expressions into a single such expression that returns a list of results, by performing each of the argument expressions in sequence and collecting their results:

```
sequence :: Monad m => [m a] -> m [a]
sequence [] = return []
sequence (ma : mas) = do a <- ma
b <- sequence mas
return (a : b)
sequence' [] = return []
sequence' (ma : mas) = ma >>= \a ->
sequence' mas >>= \b ->
return (a : b)
```

See the library Control.Monad for *many* more general purpose monad operations.

## Monads As Programmable Semicolon

It is sometimes useful to sequence two monadic expressions, but discard the result value produced by the first:

```
f (3);
g (3);
```

```
(>>) :: Monad m => m a -> m b -> m b
mx >> my = undefined
```

For example, in the state monad the `>>`

operator is just normal sequential composition, written as `;`

in most languages. Without using layout for the `do`

notation, sequencing is a semicolon too.

```
hello :: IO ()
hello = putChar 'H' >> putChar 'e' >> putChar 'l' >> putChar 'l' >> putChar 'o'
```

```
hi = do
putChar 'H'
putChar 'i'
return ()
```

Indeed, in Haskell the entire `do`

notation with or without `;`

is just syntactic sugar for `>>=`

and `>>`

. For this reason, we can legitimately say that Haskell has a *programmable semicolon*.

## Exercise

Define

`liftM`

and`join`

more compactly by using`>>=`

.Explain the behavior of sequence for the maybe monad.

`data State s a = S (s -> (a, s))`

# The monad laws

Earlier we mentioned that the notion of a monad requires that the return and `>>=`

functions satisfy some simple properties. The first two properties concern the link between return and `>>=`

:

```
return x >>= f = f x -- (1)
mx >>= return = mx -- (2)
```

Intuitively, equation (1) states that if we return a value `x`

and then feed this value into a function `f`

, this should give the same result as simply applying `f`

to `x`

. Dually, equation (2) states that if we feed the results of a computation `mx`

into the function return, this should give the same result as simply performing `mx`

. Together, these equations express --- modulo the fact that the second argument to `>>=`

involves a binding operation --- that return is the left and right identity for `>>=`

.

The third property concerns the link between `>>=`

and itself, and expresses (again modulo binding) that `>>=`

is associative:

`(mx >>= f) >>= g = mx >>= (\x -> (f x >>= g)) -- (3)`

Note that we cannot simply write `mx >>= (f >>= g)`

on the right hand side of this equation, as this would not be type correct.

As an example of the utility of the monad laws, let us see how they can be used to prove a useful property of the `liftM`

function above, namely that it distributes over the composition operator for functions, in the sense that:

`liftM (f . g) = liftM f . liftM g`

This equation generalizes the familiar distribution property of map from lists to an arbitrary monad. In order to verify this equation, we first rewrite the definition of `liftM`

using `>>=`

:

`liftM f mx = mx >>= \x -> return (f x)`

Now the distribution property can be verified as follows:

```
(liftM f . liftM g) mx
= ...
= liftM (f . g) mx
```

## Exercises

Show that the maybe monad satisfies equations (1), (2) and (3).

Write type signatures for the following "properties", that test that the monad laws hold for a particular monad:

```
prop_LeftUnit x f = (return x >>= f) == f x
prop_RightUnit m = (m >>= return) == m
prop_AssocMonad m f g = ((m >>= f) >>= g) == (m >>= (\x -> f x >>= g))
```

## Other topics

The subject of monads is a large one, and we have only scratched the surface here. If you are interested in finding out more, two suggestions for further reading would be to look at "monads with a zero and plus" (which extend the basic notion with two extra primitives that are supported by some monads), and "monad transformers" (which provide a means to combine monads.) For example, see sections 3 and 7 of the following article, which concerns the monadic nature of functional parsers For a more in-depth exploration of the IO monad, see Simon Peyton Jones' excellent article on the "awkward squad"

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