So let's start with the basic idea of the State Monad.
newtype MyState s a = MyState (s {- current state -}
-> (s {- New state -}, a {- New value -}))
unwrap (MyState f) = f
So now we need to implement >>=
and return
.
return
is pretty easy:
return a = MyState $ \s -> -- Get the new state
(s, a) -- and pack it into our value
In other words, this just passes the current state through with a new value.
And now >>=
(MyState f) >>= g = MyState $ \state ->
let (newState, val) = f state
MyState newF = g val
in newF state
So we get a new state, feed it into our existing state monad, then pass the resulting value/state pair into g
and return the result of that.
The total number of differences between this and the record syntax is just that I had to manually define unwrap
.
To complete our monad
runState = unwrap
get = MyState \s -> (s, s)
put a = MyState \s -> (a, ())