Note: It is highly recommended that you understand the State monad before reading this article.

The State monad almost feels magical, with its ability to seemingly mutate a value in-place. However, I will walk you through the steps to build your own State monad using two different methods, namely operational and free monads.

Part 1: Operational Monads

An operational monad allows you to build your own custom monad using a set of primitive instructions. One is provided in the operational package, and it is called Program .

First, you have to import the Control.Monad.Operational module. Now let’s get crackalackin!

Creating the primitives

We are going to use a GADT (generalized algebraic datatype) called StateCmd to represent the primitives. This is available through the GHC extension -XGADTs . If you don’t know what a GADT is, think of it as a normal algebraic datatype where the constructors are specialized to different types. That probably didn’t help you, so let’s show what the type will look like:

data StateCmd s a where

Get :: StateCmd s s

Put :: s -> StateCmd s ()

This implements the Get and Put primitives from the State monad. Now, we’re going to create the State monad!!!

type State s a = Program (StateCmd s) a

I know you absolutely want to implement the runState function to tear this little h*cker down, but we have to make a couple helper functions to make the primitives usable.

get :: State s s

get = singleton Get put :: s -> State s ()

put x = singleton (Put x)

It would be an absolute waste of time to keep typing singleton before each command, so whether you like it or not, we’re creating these functions.

Creating runState

The operational package provides a function called view to split the program into the head instruction and a continuation to the rest of the program. (Also, it provides a Return constructor to signify the end of the program.) Let’s show this in action:

runState :: State s a -> s -> (a, s)

runState p s = case (view p) of

Return x -> (x, s)

Get :>>= k -> runState (k s) s

Put x :>>= k -> runState (k ()) x

In English, this has three cases for the view: the Return case, where the program is over; the Get case, where the program is requesting the current state; and the Put case, where the program is requesting that the current state be changed. The continuation that is passed in the non- Return cases is how the runState function responds to the program’s requests.

Wrapping up and trying it out

Our operational State monad is fully implemented. Now, let’s do something cool with it! We’re going to implement a fibonacci function using this slightly modified example from the Haskell wiki:

import Control.Monad (forM_) fib' :: (Integral a) => a -> State (a, a) a

fib' n = do

forM_ [1..n] $ \_ -> do

(a, b) <- get

put (b, a+b)

(a, b) <- get

return a



fib :: (Integral a) => a -> a

fib n = fst $ runState (fib' n) (0, 1)

Run this example with your custom State monad, and it should work perfectly!

Part 2: Free Monads

Very similar and closely related to operational monads, I present you free monads. A free monad is a monad where everything about it is inferred from its Functor instance. You may wonder where we are going to get a functor from. The functor is in the primitives! Let’s add Control.Monad.Free to the imports.

Creating the primitives

Unlike the operational monad, where we used a GADT, we are simply going to use a normal datatype, which looks like this:

data StateCmd s a = Get (s -> a) | Put s a

Unlike in the operational monad, where it created the continuations for us, we have to explicitly specify them. Now we are going to create the functor instance:

instance Functor (StateCmd s) where

fmap f (Get k) = Get (f . k)

fmap f (Put x k) = Put x (f k)

If this makes you uncomfortable, bored, tired, or nauseous, you can use the -XDeriveFunctor GHC extension, where you can simply add deriving (Functor) to the end of the datatype declaration. Now, we shall define the State monad:

type State s a = Free (StateCmd s) a

If this looks similar to the definition of the State operational monad, that’s because operational and free monads are similar. Now, unlike the operational monad, where you had to manually define the monadic primitives, the free monad has a Template Haskell helper function to create those automatically. (This requires the -XTemplateHaskell and -XFlexibleContexts GHC extensions. Don’t worry, these are the last extensions.) To do that, simply add Control.Monad.Free.TH to your imports, and add this line after the State declaration:

makeFree ''StateCmd

This automatically creates the get and put functions. How cool is that?!

Creating runState

Unlike operational monads, where you had to view the program to get the latest instruction, the Free monad is the instructions. (The analogue of Return in the operational monad is Pure in the free monad, as with (:>>=) and the somewhat confusingly-named Free .) Let’s try it out:

runState :: State s a -> s -> (a, s)

runState p s = case p of

Pure x -> (x, s)

Free (Get k) -> runState (k s) s

Free (Put x k) -> runState k x

Notice how you don’t have to explicitly pass in the unit () in the Put case, because the free monad does that for you.

Wrapping up and trying it out

Now that we’ve finished the free State monad, try out the fibonacci example from earlier in the operational example.

Final notes

I hope you learned something about how the State monad works, and how to use operational and free monads!

The code can be found at a GitHub gist here!