0

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?

2
  • MonadState is the type class for monads such as State: hackage.haskell.org/package/mtl-2.2.1/docs/… Commented Aug 24, 2016 at 13:48
  • What research have you done to answer this question yourself? Have you read the documentation? Have you googled for MonadState? Commented Aug 24, 2016 at 15:56

2 Answers 2

4

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
    ...
Sign up to request clarification or add additional context in comments.

Comments

3

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)

1 Comment

If I'm not wrong, using a concrete type with MonadState in the signature requires enabling the FlexibleInstances.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.