class Monad m => MonadState s m | m -> s where
-- | Return the state from the internals of the monad.
get :: m s
get = state (\s -> (s, s))
-- | Replace the state inside the monad.
put :: s -> m ()
put s = state (\_ -> ((), s))
-- | Embed a simple state action into the monad.
state :: (s -> (a, s)) -> m a
state f = do
s <- get
let ~(a, s') = f s
put s'
return a
instance MonadState s m => MonadState s (MaybeT m) where...
Why does a instance of MonadState need a state and a monad, why not create a single parameter State class?
Let me try and answer Gert's question in the comments, because it's a pretty different question.
The question is, why can we not just write
class State s where
get :: s
put :: s -> ()
Well, we could write this. But now the question is, what can we do with it? And the hard part is, if we have some code with put x
and then later get
, how do we link the get
to the put
so that the same value is returned as the one put in?
And the problem is, with just the types ()
and s
, there is no way to link one to the other. You can try implementing it in various ways, but it won't work. There's just no way to carry the data from the put
to the get
(maybe someone can explain this better, but the best way to understand is to try writing it).
A Monad is not necessarily the only way to make operations linkable, but it is a way, because it has the >>
operator to link two statements together:
(>>) :: m a -> m b -> m b
so we can write
(put x) >> get
EDIT: Here is an example using the StateT
instance defined in the package
foo :: StateT Int IO ()
foo = do
put 3
x <- get
lift $ print x
main = evalStateT foo 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With