I find it difficult for me to understand the MonadState .
The reason maybe most of the examples mixing up with record syntax in their data structure.
So, I tried to implement the MonadState without using record syntax.
The following code I wrote did pass the compiler, but it seems totally nonsense to me.
What is wrong with these code?
Is there a simple example of implementing MonadState without using record syntax?
data Foo a b = Foo (Maybe ([a],b)) deriving (Show)
unwrapFoo :: Foo a b -> Maybe ([a],b)
unwrapFoo (Foo x) = x
instance Monad (Foo [a]) where
return x = Foo $ Just ([], x)
m >>= f = case unwrapFoo m of
Just (_, r) -> f r
Nothing -> Foo Nothing
instance MonadState Int (Foo [a]) where
get = Foo $ Just ([], 1)
put _ = Foo $ Just ([],())
*Main> get :: Foo [a] Int
Foo (Just ([],1))
*Main> put 3 :: Foo [a] ()
Foo (Just ([],()))
*Main>
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, ())