为什么MonadReader r(StateT sm)使用底层monad的实例

pha*_*dej 4 haskell monad-transformers

据我所知,我们可以实现MonadReader s (StateT s m)实例:

instance MonadReader s (StateT s m) where
    ask = get
    local f m = do
        s <- get
        put (f s)
        m
        put s   
Run Code Online (Sandbox Code Playgroud)

即为什么不是

class MonadReader s m => MonadState s m | s -> m where ...
Run Code Online (Sandbox Code Playgroud)

同样,我们可以有Monoid s => MonadWriter s (StateT s m)实例.

选择之间有一些深层次的原因吗?


这个问题是由动机是否MonadErrorMonadWriter应是超类MonadChronicle

dfe*_*uer 7

是的,你可以这样做,但它会违反精神mtl并可能导致API问题.想法mtl是每个标准monad变换器添加一个或多个不同的效果.添加StateTReaderT转换器堆栈为您提供状态和环境.如果StateT实现了自己的MonadReader实例,那么您可以通过两个不同的接口访问状态blob.要为混合添加环境,您必须"手动"使用变压器.如果您认为MonadChronicle提供效果可能需要在编写器和异常效果之上进行分层,那么您应该将它们分开.如果您将其视为这些效果的扩展/细化,那么超类就有意义了.

  • @phadej我会称之为`State2`或其他东西,但不是'RWS`,因为`RWS`的要点是保证只读部分和保证仅附加部分,超出了读/写部分州.如果只有`s`,我想我们实际上有一个`State` newtype,除了更多的实例(由于你提到的原因,这不是一个坏主意). (3认同)