Why use MultiParamTypeClasses in MonadState

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 MonadState instance require state and monad, why not create one class State class?

+5
source share
2 answers

Let me try to answer Herth's question in the comments, because that is a rather different question.

The question is, why can't we just write

class State s where
   get :: s
   put :: s -> ()

Well, we could write this. But now the question is, what can we do about it? And the hard part is, if we have c code put x, and then gethow do we bind getto putso that the return value is returned the way it was inserted?

, () s . -, . put get ( , - , - ).

, , >> :

(>>) :: m a -> m b -> m b

(put x) >> get

EDIT: , StateT,

foo :: StateT Int IO ()
foo = do
    put 3
    x <- get
    lift $ print x

main = evalStateT foo 0
+6

- . MultiParamTypeClasses FunctionalDependencies . TypeFamilies.

class (Monad m) => MonadState m where
    type StateType m

    -- | Return the state from the internals of the monad.
    get :: m (StateType m)
    get = state (\s -> (s, s))

    -- | Replace the state inside the monad.
    put :: StateType m -> m ()
    put s = state (\_ -> ((), s))

    -- | Embed a simple state action into the monad.
    state :: (StateType m -> (a, StateType m)) -> m a
    state f = do
      s <- get
      let ~(a, s') = f s
      put s'
      return a

instance MonadState m => MonadState (MaybeT m) where
    type StateType (MaybeT m) = StateType m

    ...

, monads-tf package.

+4

All Articles