I am trying to get a grasp on Haskell using the online book Learn you a Haskell for great Good.
I have, to my knowledge, been able to understand Monads so far until I hit the chapter introducing the State Monad.
However, the code presented and claimed to be the Monad implementation of the State type (I have not been able to locate it in Hoogle) seems too much for me to handle.
-
To begin with, I do not understand the logic behind it i.e why it should work and how the author considered this technique.( maybe relevant articles or white-papers can be suggested?)
-
At line 4, it is suggested that function f takes 1 parameter.
However a few lines down we are presented with pop, which takes no parameters! -
To extend on point 1, what is the author trying to accomplish using a function to represent the State.
Any help in understanding what is going on is greatly appreciated.
Edit
To whom it may concern,
The answers below cover my question thoroughly.
One thing I would like to add though:
After reading an article suggested below, I found the answer to my second point above:
All that time I assumed that the pop function would be used like :
stuff >>= pop since in the bind type the second parameter is the function, whereas the correct usage is this pop >>= stuff , which I realized after reading again how do-notation translates to plain bind-lambdas.
Short answer:
Stateis meant to exploit monads’ features in order to simulate an imperative-like system state with local variables. The basic idea is to hide within the monad the activity of taking in the current state and returning the new state together with an intermediate result at each step (and here we haves -> (a,s).State. The former may have whatever type you want (provided that they eventually produce someState aif you want to use them in the state monad). The latter holds functions of types -> (a,s): this is the state-passing layer managed by the monad.Stateis actually produced by means of(>>=)andreturnas they’re defined for theMonad (State s)instance. Its role is to pass down the state through the calls of your code.Point 3 also is the reason why the state parameter disappears from the functions actually used in the state monad.
Long answer:
The State Monad has been studied in different papers, and exists also in the Haskell framework (I don’t remember the good references right now, I’ll add them asap).
This is the idea that it follows: consider a type
data MyState = ...whose values holds the current state of the system.If you want to pass it down through a bunch of functions, you should write every function in such a way that it takes at least the current state as a parameter and returns you a pair with its result (depending on the state and the other input parameters) and the new (possibly modified) state. Well, this is exactly what the type of the state monad tells you:
s -> (a, s). In our example,sisMyStateand is meant to pass down the state of the system.The function wrapped in the
Statedoes not take parameters except from the current state, which is needed to produce as a result the new state and an intermediate result. The functions with more parameters that you saw in the examples are not a problem, because when you use them in thedo-notation within the monad, you’ll apply them to all the “extra” needed parameters, meaning that each of them will result in a partially applied function whose unique remaining parameter is the state; the monad instance forStatewill do the rest.If you look at the type of the functions (actually, within monads they are usually called actions) that may be used in the monad, you’ll see that they result type is boxed within the monad: this is the point that tells you that once you give them all the parameters, they will actually do not return you the result, but (in this case) a function
s -> (a,s)that will fit within the monad’s composition laws.The computation will be executed by passing to the whole block/composition the first/initial state of the system.
Finally, functions that do not take parameters will have a type like
State awhereais their return type: if you have a look at the value constructor forState, you’ll see again that this is actually a functions -> (a,s).