Mat*_*ick 9 monads haskell monad-transformers
我正在尝试学习monad变换器,基于标准的Haskell库(mtl?变换器?不确定哪一个来自我的Haskell平台下载 - 7.4.1).
我相信我注意到的是每个monad变换器定义的通用结构:
基本类型('基础')
变压器类型('BaseT')
Monad实例
MonadTrans实例
MonadIO实例
变压器类('MonadBase')
一些操作
其他'BaseT'的实例
因此,例如,对于Writer monad,会有:
这是monad变形金刚的组织方式吗?我错过了什么/我有任何不正确的细节吗?
这个问题的动机是搞清楚:
mtl包没有实现 monad 转换器。至少 WriterT刚刚从transformers.
transformerspackage Implements WriterT,它本身就是一个 monad 转换器。Writer只是一个别名:
type Writer w = WriterT w Identity
Run Code Online (Sandbox Code Playgroud)
有些库可以Writer单独实现,但无论如何它只是WriterT. (Identity是一个简单的 monad,它没有任何额外的行为。)
MonadTrans允许您将底层 monad 包装到转换后的 monad 中。您可以没有它,但您将需要执行手动包装(请参阅MonadTrans实例定义以了解WriterT如何执行此操作的示例)。MonadTrans当您不知道变压器的实际类型时,您真正需要的唯一用例。
MonadWriter是在 中声明的类型类mtl。它的方法(、 和writer)pass与的函数相同。它允许(自动!)通过变压器堆栈进行计算,即使您不知道堆栈中变压器的确切类型(甚至数量!)。telllistenWriterTWriterT
因此,WriterT这是唯一“必需”的类型。
对于其他 monad 转换器,它是相同的:BaseT是一个转换器,Base是一个没有底层 monad 的 monad,并且MonadBase是一个类型类——所有 monad 的类,BaseT在转换器堆栈中的某个位置。
添加:
你可以在RWH 书中找到很好的解释
这是一个基本示例:
import Control.Monad.Trans
import Control.Monad.Trans.Writer
import Control.Monad.Trans.Reader hiding (ask)
-- `ask` from transformers
-- ask :: Monad m => ReaderT r m r
import qualified Control.Monad.Trans.Reader as TransReader (ask)
-- `ask` from mtl
-- ask :: MonadReader r m => m r
import qualified Control.Monad.Reader as MtlReader (ask)
-- Our monad transformer stack:
-- It supports reading Int and writing String
type M m a = WriterT String (ReaderT Int m) a
-- Run our monad
runM :: Monad m => Int -> M m a -> m (a, String)
runM i action = runReaderT (runWriterT action) i
test :: Monad m => M m Int
test = do
tell "hello"
-- v <- TransReader.ask -- (I) will not compile
v1 <- lift TransReader.ask -- (II) ok
v2 <- MtlReader.ask -- (III) ok
return (v1 + v2)
main :: IO ()
main = runM 123 test >>= print
Run Code Online (Sandbox Code Playgroud)
请注意,这(I)将被编译器拒绝(尝试查看错误消息!)。但(II)由于MonadTrans(“显式提升”),可以编译。感谢MonadReader,(III)开箱即用(“隐式提升”)。请阅读 RWH 书籍以了解其工作原理。
(在示例中,我们ask从两个不同的模块导入,这就是我们需要限定导入的原因。通常您一次只会使用其中一个。)
而且我也不是故意要特别问的
Writer。
不确定我理解... Reader,State其他人使用相同的模式。替换Writer为State,您将得到解释State。