User:Davjam2:Example/StateMonad

Handling Combined States
Suppose we wanted to create a random turnstile, where each visitor would be given a random turnstile input: either they insert a coin (but are not allowed through); or they get to push the arm (and go through if it opens, but are otherwise sent away).

Here's one useful bit of code:

This allows us to generate random  values. However, our random turnstile machine needs to track both the state of a random number generator and the state of the turnstile. We want to write a function like this:

And this function needs to call both  (which is in the   monad) and   (which is in the   monad).

Much of the code in  deals with managing the state: accessing the combined state, unpacking subcomponents, forwarding them to the individual State monads, recombining them and putting the combined state back. The state management code is not too bad in this case, but could easily become cumbersome in a more complex function. And it is something we wanted the  monad to hide from us.

State-Processing a Subcomponent
Ideally we'd want some utility function(s) that allow us to invoke a  monad function (or   monad function) from within a   monad function. These function(s) should take care of the state management for us, ensuring that the right subcomponent of the combined state is updated.

Here's one such a function that works for any combined state represented as a pair, and performs the state update on the fst of the pair:

Note the type:

"converts" a  monad (in this case with state type  ) to another   monad (in this case with state type , where   can be any type, even a  ).

Note how  is no longer directly involved in the details of the state management, and its business logic is much more apparent.

Generic Subcomponent Processing
We can see that  and   are very similar. They both extract a subcomponent of a combined state,  on that subcomponent, then update the combined state with the new value of the subcomponent.

Let's combine them into a single generic subcomponent processing function. To do this, we could pass in separate parameters, one of type  (a function that extracts a subcomponent from a combined state value), and another of type   (a function that, given a combined value and a new value for a subcomponent, returns the revised combined value with the updated subcomponent). However, it's a bit neater to package these two functions together in a type which we'll call :

We can provide specific lenses onto the fst and snd elements in a pair:

So now:

We can now replace  and   with our generic function.

Our final random turnstile code is neater, with three separate logical functions segregated:
 * state management (now in a single  utility function, which can be reused elsewhere);
 * subcomponent accessing and update (using . We could use a standard package for this, which also provides many more lenses, automatic creation of lenses on custom data types, easy combining of lenses for deeply-nested subcomponents, etc); and
 * the "business logic" of the turnstile, which is now very apparent.

In our first implementation, all three of these were muddled together.

Let's give it a go:

I'm not sure we'll sell many of them, though.