Gia*_*eri 4 monads haskell monad-transformers reader-monad
作为练习,我一直在重新实现一些常见的 monad 及其相应的转换器;以下是我定义的一些类型:
newtype Writer w a = Writer { runWriter :: (w, a) }
newtype WriterT w m a = WriterT { runWriterT :: m (Writer w a) }
newtype Maybe a = Just a | Nothing
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
Run Code Online (Sandbox Code Playgroud)
据我所知,变压器将一个单子“包裹”在一个外部单子中m;遵循这种直觉,我尝试ReaderT以类似的方式定义变压器:
newtype Reader r a = Reader { runReader :: r -> a }
newtype ReaderT r m a = ReaderT { runReaderT :: m (Reader r a) }
Run Code Online (Sandbox Code Playgroud)
然而,我在实现它的 monad 实例时遇到了困难。通过查看库定义,ReaderT我发现它被定义为
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
Run Code Online (Sandbox Code Playgroud)
Reader除了它不使用(可以用 定义)这一事实之外ReaderT,为什么它被定义为r -> m a和 not m (r -> a)?我认为它应该用外部单子来包裹内部Reader(即)而不是r -> amm (r -> a)r -> m a
m (r -> a)意味着您:
首先在 monad 中执行一些操作,然后,
\n动作完成后后,对reader值进行纯计算。
\n但你需要能够使用ask:
ask :: Monad m => ReaderT r m r\nRun Code Online (Sandbox Code Playgroud)\n和ask,您可以:
首先读取值,
\n然后执行一些单子操作,作用于该值。
\n这就是为什么r -> m a有道理并且m (r -> a)没有道理的原因。
如果有帮助,请将其视为 \xe2\x80\x9csymmatical\xe2\x80\x9d 和 writer monad。对于 writer monad,monad 位于外部,结果位于内部。对于阅读器 monad,输入位于外部,而 monad 位于内部。这种对称性经常出现。
\n