Your are likely using the MonadState
typeclass without being aware of it. This typeclass is defined in the mtl
package (and in monads-fd
, too).
MonadState
allows you to use the methods of the State
monad, directly and without explicit lifting, in many monad stacks based on State
.
Look at the following two lines in the haddocks:
Monad m => MonadState s (StateT s m)
MonadState s m => MonadState s (ReaderT r m)
The first one says that any StateT
is an instance of MonadState
(as we should expect!). The second one says that any ReaderT
whose base monad is an instace of MonadState
, is also an instance of MonadState
. Which happens to be your case.
Looking at the source code for MonadState
, we find:
instance MonadState s m => MonadState s (ReaderT r m) where
get = lift get
put = lift . put
state = lift . state
modify :: MonadState s m => (s -> s) -> m ()
modify f = state (\s -> ((), f s))
As you see, the inner machinery of the typeclass takes care of the lifting.
There are other typeclasses which offer similar functionality, like MonadReader
, MonadWriter
and MonadRWS
.