Cheatsheet: Stacking the State and Either Monads

Posted on April 2, 2018

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.

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