As far as I can see, we could implement MonadReader s (StateT s m)
instance:
instance MonadReader s (StateT s m) where
ask = get
local f m = do
s <- get
put (f s)
m
put s
i.e. why it isn't
class MonadReader s m => MonadState s m | s -> m where ...
Similarly we could have Monoid s => MonadWriter s (StateT s m)
instance.
Is there some deep reason between the choice?
This question is motivated by whether MonadError
and MonadWriter
should be
super classes of MonadChronicle
Yes, you could do that, but it would violate the spirit of mtl
and potentially lead to API issues. The idea of mtl
is that each standard monad transformer adds one or more distinct effects. Adding StateT
and ReaderT
to the transformer stack give you a state and an environment. If StateT
implemented its own MonadReader
instance, then you'd have access to just the state blob, through two different interfaces. To add an environment to the mix, you'd have to work with the transformers "manually". If you see MonadChronicle
as offering effects you might want to layer on top of writer and exception effects, then you should keep them separate. If you see it as an extension/refinement of those effects, then superclasses make sense.
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