Haskell/Understanding monads/Solutions/State

Sequencing Steps
1.

2.

3.

Using the Turnstile monad
1.

2.

Accessing the State
1.

2.

3.

Monadic Control Structures
1.

2.

3.

4.

5. The only change needed is the type signature:

Note that  has replaced.

Example: Rolling Dice
1. Here's a very tedious solution:

Here's a slightly better solution: do the next question first, then.

2.

This is at least quite short and not tedious, but it is not the easiest to understand.

Dice with
1.

Somewhat less tedious than

2.

Quite a bit easier to follow that.

3.

is also a and an
1.

2.

3.

4. We can't write  using just   and   (or  ), since the number of actions taken depends on the result of the first action. (Compare this to, which does make some decisions based on the result of the first action, but these decisions don't include whether to execute the second action.)

We need to use  (or do notation), but we can simplify it a little:

5.

6.

The type of, specialised to   is   (although the brackets around   are usually omitted). The first parameter is a function mapping an  to a. The second is a  value, i.e. a wrapper of a state-processing step which, when executed, will give a value of type   (whilst also determining a new state of type   from the original). The result has to be a, which is just like the   except that, when executed, instead of returning the  , the   mapping is applied to the  , and we get a   instead. And it also has to return exactly the same updated state as the  would.

Here goes:

The type of  is. Given any value, it creates a state-processing step which, when executed, returns that very value. It also returns the original state with no changes:

The type of  is. It's like, except that the   mapping function is only obtained by executing the first state processing step. And also, we have to make sure that we execute the state-processing step to get the mapping function (and a new state) before we execute the step to get the  value, and make sure we thread the updated state between them.

We could do this:

Except that uses do notation, and hence the  code that we're not allowed to use. So instead, we do the pre-enlightenment tedious state threading:

You may wonder how we can check we've coded these correctly. One thing we should do is check they comply with the relevant laws, including the Functor laws. The first states that, if we've done it right:

Let's check, using our "slightly tidied" definition from above:

We should also check the other (composition) law for functors, and also the laws for applicatives and monads. (I will leave that as an exercise for the reader).

Confirming they comply with the laws is a necessary to confirm they're correct, but not by itself sufficient.

(Probably) don't or
1.

2.

Handling Combined States
1.

State-Processing a Subcomponent
1.

2.

Generic Subcomponent Processing
1.

2.