我试着学习单台变压器,基于标准的Haskell库(mtl?变形金刚?不知道我下载的Haskell平台-7.4.1附带的是哪一个)。
我认为我注意到的是每个单台转换器定义的公共结构:
- Monad instance
- Monad instance
- MonadTrans instance
- MonadIO instance
- some operations
- instances for other 'BaseT's
例如,对于Writer monad,应该有:
这就是单台变压器的组织方式吗?我遗漏了什么吗?我有什么不正确的细节吗?
这个问题的动机是找出:
发布于 2012-11-28 17:40:12
mtl包不实现单台变压器。至少WriterT只是来自transformers的再出口。
transformers包实现了WriterT,它本身就是一个单台转换器。Writer只是一个别名:
type Writer w = WriterT w Identity有些库可以单独实现Writer,但无论如何,这只是WriterT的一个特例。(Identity是一个微不足道的单子,它没有任何附加的行为。)
MonadTrans允许您将底层单块封装到转换后的单块中。您可以不使用它,但您需要执行手动包装(例如,请参阅MonadTrans实例定义中的WriterT )。唯一真正需要MonadTrans的用例--当您不知道实际类型的转换器时。
MonadWriter是在mtl中声明的类型类。它的方法(writer、pass、tell和listen)与WriterT的函数相同。它允许(自动!) WriterT计算通过变压器堆栈,即使你不知道确切的类型(和偶数!)堆里的变压器。
因此,WriterT是唯一“必需”的类型。
对于其他单台变压器来说是一样的: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和其他人使用相同的架构。将Writer替换为State,您将得到对State的解释。
https://stackoverflow.com/questions/13609626
复制相似问题