Monad变压器的解剖
我试图学习基于标准Haskell库(mtl?变换器?不知道哪一个随我下载了Haskell平台 - 7.4.1)的monad变换器。
我相信我已经注意到每个monad变压器定义的通用结构:
基本类型('基本')
变压器类型('BaseT')
Monad实例
MonadTrans实例
MonadIO实例
变压器类('MonadBase')
一些操作
其他'BaseT's的实例
举个例子,对于Writer monad来说,会出现:
这是如何monad变压器组织? 我错过了什么/我有任何不正确的细节?
这个问题的动机是搞清楚:
mtl
包不会实现monad变换器。 至少WriterT只是从transformers
重新出口。
transformers
包实现WriterT
,它本身就是一个单体变压器。 Writer
只是一个别名:
type Writer w = WriterT w Identity
有些库可以单独实现Writer
,但无论如何这只是WriterT
。 ( Identity
是一个微不足道的monad,它没有任何额外的行为。)
MonadTrans
允许您将底层monad包装到转换后的monad中。 你可以没有它,但你需要(见执行手动包装MonadTrans
例如定义WriterT
例如如何做到这一点)。 您真正需要MonadTrans
的唯一用例 - 当您不知道变压器的实际类型时。
MonadWriter
是以mtl
声明的类型类。 它的方法( writer
, pass
, tell
和listen
)与WriterT
功能相同。 它允许通过堆栈变换器来自动换行(自动!) WriterT
计算,即使您不知道堆栈中变压器的确切类型(甚至数字!)。
所以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
请注意, (I)
将被编译器拒绝(尝试查看错误消息!)。 但(II)
编译,感谢MonadTrans
(“显式提升”)。 感谢MonadReader
, (III)
开箱即用(“隐式提升”)。 请阅读RWH书籍以了解它的工作原理。
(在我们导入例如ask
从两个不同的模块,这就是为什么我们需要合格的进口。通常你会在同一时间只能使用其中的一个。)
我也不是故意专门询问Writer
。
不知道我明白... Reader
, State
和其他人使用相同的模式。 用State
代替Writer
,你将会得到State
的解释。
上一篇: Anatomy of a monad transformer
下一篇: How to cleanly convert between lists and ListT monad transformers?