So I have recently been looking at state monads because I want to build a parser combinator library in haskell.
I came across a typeclass known as MonadState, I was wondering what is the point of this typeclass and where would you use it?
MonadState abstracts out the get and put functions so that they work not just for one type, but for any type that can act as a state monad. It's primarily to make monad transformers work.
Without going into too much detail, let's just assume you know that StateT exists: it takes one monad and returns a new monad that can act as state. (I'll ignore the difference between lazy and strict state monads here). A monad that handles state can then be defined by applying StateT to the Identity monad:
newtype State s = StateT s Identity
As long as the input type is a monad, we can provide a MonadState instance for the monad returned by StateT:
-- Add state to any monad
instance Monad m => MonadState s (StateT s m) where
...
This says that applying StateT to any monad (not just Identity) produces a monad that can be treated as a state monad.
Further, you can say that anything that wraps a state monad is also a state monad, as long as it implements MonadState:
-- Add Maybe to a state monad, it's still a state monad
instance MonadState s m => MonadState s (MaybeT m) where
...
-- Add Writer to a state monad, it's still a state monad
instance (Monoid w, MonadState s m) => MonadState s (WriterT w m) where
...
MonadState abstracts the state monad (as if this stuff wasn't abstract enough, right?). Instead of requiring a concrete type State with a Monad instance, it lets us use any Monad we like, provided we can provide appropriate get and put functions. In particular, we can use StateT which lets us combine effects.
simple example combining State and IO:
tick :: (MonadIO m, MonadState Int m) => m ()
tick = do
x <- get
liftIO $ putStrLn ("incrementing " ++ (show x))
put (x+1)
> runStateT (tick >> tick >> tick >> tick) 5
incrementing 5
incrementing 6
incrementing 7
incrementing 8
((),9)
MonadState in the signature requires enabling the FlexibleInstances.
MonadStateis the type class for monads such asState: hackage.haskell.org/package/mtl-2.2.1/docs/…MonadState?