*Note: this is the completed version of lecture STMonad. The lhs version of this file is available.*

# The ST and IO Monads

`> module STMonad where`

```
> import Control.Monad (forM_)
> import qualified Data.Vector.Mutable as V
```

In this example, we will discuss the connection between Haskell's implementation of the `State`

monad and the `IO`

monad. GHC's version plays a trick to allow a much more efficient implementation of the `State`

monad than we could do using pure Haskell.

`> import Control.Monad.ST`

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

The presence of `return`

and `>>=`

means that we can treat `IO`

as a monad, and hence (as we've seen) that the `do`

notation can be used to write imperative programs.

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

One way to understand the `IO`

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

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

That is, an IO 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 other words, we have this correspondence:

In reality, Haskell systems such as GHC implement actions in a more efficient manner, but for the purposes of understanding the behavior of actions, the above interpretation can be useful.

## Mutable Arrays in Haskell

The two most important actions associated with the State Monad are accessing and modifying the `Store`

.

```
get :: State Store Store
put :: a -> Store -> State Store ()
```

What does this mean for the interpretation of the IO monad as the State monad, using the 'RealWorld' as the state?

` type IO a = State RealWorld a`

In this case, `get`

and `put`

are not realistic. We cannot expect our program to give us access to a reference to the entire `RealWorld`

? What would we do with it? Furthermore, we shouldn't be able to change out the entire `ReadWorld`

with a new version (assuming we could construct one in the first place).

Instead, the IO monad gives us access to *part* of the real world. For example, the IO monad can give us access to a part of the computer's memory, such as a mutable reference or mutable array.

The `Data.Vector.Mutable`

library provides support for working with mutable arrays in Haskell using an interface that looks somewhat like the following:

```
type MVector e -- type of arrays containing elements of type e
read :: MVector e -> Int -> IO e
write :: MVector e -> Int -> e -> IO ()
replicate :: Int -> e -> IO (MVector e)
replicateM :: Int -> IO e -> IO (MVector e)
length :: MVector e -> Int
```

You can think of a `MVector`

as a description of the part of the real world that we want to look at. In that case, `read`

and `write`

look a lot like `get`

and `put`

. The only difference is we need to say what part of the store we want to use with get and put (i.e. the `MVector`

); we aren't working with the entire store.

The `replicate`

operation allows us to construct vectors (i.e. define a part of the RealWorld that we want access to). The `Int`

is the length of the vector, and the `e`

argument is used to provide an initial value to all of the arguments of the vector.

For example, the code below constructs a new vector of length 100, prints out its length, writes to a particular location in that vector, and then accesses the data from that same location. The analogous Java code for each line is in the comments.

```
> example = do
> v <- V.replicate 100 Nothing -- Char[] v = new Char[100];
> putStrLn (show (V.length v)) -- System.out.println(v.length);
> V.write v 10 (Just 'a') -- v[10] = 'a';
> x <- V.read v 10 -- Int x = v[10];
> putStrLn (show x) -- System.out.println(v[10]);
```

Other than Haskell's lack of convenient notation for array access and update, the two versions are comparable.

We can also create multidimensional arrays as vectors of vectors.

Initialize a 2-D array of size n m with 0s. (The commented type is not the real type of the function, but a useful fiction for now.)

```
> -- make_matrix :: Int -> Int -> IO (MVector (MVector Int))
> make_matrix n m =
> V.replicateM n (V.replicate m 0)
```

Read from location i j in the vector.

```
> -- read_matrix :: MVector (MVector Int) -> Int -> Int -> IO Int
> read_matrix vec i j = do
> m0 <- V.read vec i
> V.read m0 j
```

Write the value x at location i j in the vector.

```
> -- write_matrix :: MVector (MVector Int) -> Int -> Int -> Int -> IO ()
> write_matrix vec i j x = do
> m0 <- V.read vec i
> V.write m0 j x
```

As a larger example, we can construct 2-dimensional arrays and use them to solve the classic dynamic programming problem of making change.

```
> -- given a list of coin values, and a total amount,
> -- determine the smallest number of coins that can be used
> -- to make change for that amount.
> make_changeM :: [Int] -> Int -> IO Int
> make_changeM coins n = do
> -- initialize the change making matrix
> let num_coins = length coins
> m <- make_matrix (num_coins + 1) (n + 1)
> forM_ [ 0 .. n ] $ \i -> do
> write_matrix m 0 i i
> -- go through each of the coin values (and their indices)
> forM_ (zip coins [ 1 .. num_coins ]) $ \(c,ci) ->
> forM_ [ 1 .. n ] $ \r -> do
> if (c == r) then
> -- Use that coin
> write_matrix m ci r 1
> else if (c > r) then do
> -- We use the previous solution for making r,
> -- excluding coin c
> v <- read_matrix m (ci-1) r
> write_matrix m ci r v
> else do
> -- We can use c
> -- We need to decide which one of the following solutions is the best:
> -- 1. Using the previous solution for making r
> -- (without using c)
> -- 2. Using the previous solution for making r - c
> -- (without using c) plus this 1 extra coin.
> -- then write that answer at position ci
> v1 <- read_matrix m (ci - 1) r
> v2 <- read_matrix m ci (r - c)
> write_matrix m ci r (min v1 (1 + v2))
> read_matrix m num_coins n
```

## Local State and the ST monad

One thing to notice about `makeChangeM`

above is that all of the state that is use by this function is *local* to the function. It needs to allocate the 2D array, but once the answer is calculated, this array does not persist past the execution of this function.

In this case, it is somewhat annoying that the type of `makeChangeM`

has `IO`

in it. We should be able to treat it like a pure functional program.

It turns out that Haskell's type system is powerful enough to allow us to do just that. The library that we have been using is actually more general than I've been showing you. The `MVector`

type in this file is really an abbreviation for a more general type that mentions the "store" that the vector is defined within.

` type MVector e = V.MVector RealWorld e`

When we use vectors from the IO monad, all we know about them is that they come from the real world.

However, we can also use mutable vectors in the `ST`

monad, which tracks the part of the state that they reference. For example, we could also give `make_matrix`

above the following type:

`> -- make_matrix :: Int -> Int -> ST s (V.MVector s (V.MVector s Int))`

Furthermore, the `make_changeM`

matrix also has this intriguing type~

`> -- make_changeM :: [Int] -> Int -> ST s Int`

*UPDATE THE TYPE OF make_changeM to this type RIGHT NOW*.

Types like this are where the Haskell `ST`

monad really shines. This type tells us that the function only uses *local state* and that the state doesn't escape elsewhere into the computation. How do we know that looking at the type? Because the type variable `s`

only appears once, in the result type of the function. It isn't part of any of the arguments to `make_changeM`

nor is it part of the final result type (i.e. the last parameter to `ST`

).

Because we know that this state can be isolated, we can use the `ST`

monad function below to run the computation to produce a pure value.

` runST :: (forall s. ST s a) -> a`

What this means is that if you use state in your implementation to make it faster, as long as your function is actually a function to the outside world, it doesn't need to stay in the `ST`

monad. (Whoa! This is a function that we *cannot* write in Haskell on our own.)

For example, once you change the type signature to `make_changeM`

, you can replace `undefined`

below with `(make_changeM coins n)`

.

```
> make_change :: [Int] -> Int -> Int
> make_change coins n = runST undefined
```

Note that we have to isolate the state. If we allow `s`

to escape through the result type of the ST computation

`> -- bad = runST (make_matrix 10 10)`

Or through some variable in the context that the computation refers to

```
> {-
> bad = do
> m <- make_matrix 10 10
> let y = runST (read_matrix m 5 5)
> return y
> -}
```

we will get a type error error. Try uncommenting these lines, but don't read the errors too closely --- they refer to concepts that we have not yet covered.