# Cheatsheet: Stacking the State and Either Monads

I do this rarely enough that I always have to Google for how to do it, which is a good sign that I should just write it down.

Before running the code below, install `mtl`

. Running `cabal install mtl`

works.

Here, I’ll use `Stored`

as the type of the state stored in the state monad and `Err`

as the type of the error. I could have picked any types for these two.

```
import Control.Monad.State (StateT, modify, get, put, lift, evalStateT)
import Data.Map (Map)
import qualified Data.Map as Map
type Stored = Map String Int
type Err = String
type StoreM = StateT Stored (Either Err)
note :: a -> Maybe b -> Either a b
note msg = maybe (Left msg) Right
save :: String -> Int -> StoreM ()
save k v = modify (Map.insert k v)
load :: String -> StoreM Int
load k = do
store <- get
lift $ note ("the key " ++ k ++ " is missing") (Map.lookup k store)
stateManip :: StoreM Int
stateManip = do
save "x" 1
save "x" 2
save "y" 123
x <- load "x"
y <- load "y"
save "z" (x + y)
load "z"
main = putStrLn $ show $ evalStateT stateManip Map.empty
```

`StoreM`

is the monad type.

`evalStateT`

runs your monadic function (`stateManip`

) with some starting state (`Map.empty`

, in this case).

I’ve defined two other functions in that monad: `save`

and `load`

. The `save`

function modifies the state, and it always succeeds. The `load`

function reads the state (but doesn’t modify it), and may fail. Both of these are implemented in terms of functions provided by the monad library.

I use a helper function called `note`

to convert `Nothing`

into `Left Err`

by adding an error message, but this doesn’t really have much to do with the monad. It’s just for convenience.

Besides `evalStateT`

, the key functions from `Control.Monad.State`

are `modify`

(which modifies the state value by applying some function to it), `get`

(which gives you the current state), `put`

(which replaces the current state), and `lift`

(which “converts” a function that doesn’t use state into one that does).