我正在尝试基于标准的Haskell库学习monad转换器(Mtl?转换器?不确定我下载的Haskell平台7.4.1附带了哪一个)。

我相信我注意到的是每个monad变压器定义的通用结构:

  • 基本类型(“基本”)
  • Monad实例
  • 变压器类型('BaseT')
  • Monad实例
  • MonadTrans实例
  • MonadIO实例
  • 转换器类('MonadBase')
  • 一些操作
  • 其他'BaseT的的
  • 实例

  • 因此,例如,对于Writer monad,将有:
  • Writer数据类型/新类型/类型,带有Monad实例
  • 一个WriterT数据类型/新类型/类型,带有Monad,MonadTrans和MonadIO实例
  • 一个MonadWriter类,以及该类的实例,用于StateT,ReaderT,IdentityT,...

  • 这是monad变压器的组织方式吗?我是否遗漏任何东西/我有任何不正确的详细信息吗?

    这个问题的动机是弄清楚:
  • “BaseT”与相应的“MonadBase”和“Base”的
  • 之间的关系和区别是什么
  • 是否全部三个都需要
  • MonadTrans如何关联以及其目的是
  • 最佳答案

    mtl包未实现monad转换器。至少WriterT只是transformers中的reexported
    transformers包实现了WriterT,它是monad转换器本身。 Writer只是一个别名:

    type Writer w = WriterT w Identity
    

    一些库可以单独实现Writer,但是无论如何,这只是WriterT的特例。 (Identity是一个普通的monad,它没有任何其他行为。)
    MonadTrans允许您将基础monad包装到转换后的monad中。您可以没有它,但是您将需要执行手动换行(例如,有关MonadTrans的信息,请参见WriterT实例定义)。真正需要MonadTrans的唯一用例-当您不知道转换器的实际类型时。
    MonadWriter是在mtl中声明的类型类。它的方法(writerpasstelllisten)与WriterT的功能相同。它允许通过转换器堆栈包装(自动!)WriterT计算,即使您不知道堆栈中转换器的确切类型(甚至偶数!)也是如此。

    因此,WriterT是唯一的“必需”类型。

    对于其他monad转换器,它是相同的:BaseT是转换器,Base是不具有底层monad的monad,MonadBase是类型类-所有monad的类,在转换器堆栈中的某个位置具有BaseT

    已添加:

    您可以在RWH book中找到很好的解释

    这是一个基本示例:
    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,这就是为什么我们需要合格的导入。通常您一次只能使用其中一个。)



    不确定我了解... ReaderState和其他人使用相同的架构。用Writer替换State,您将获得State的说明。

    关于haskell - monad变压器的解剖,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13609626/

    10-12 18:47