【问题标题】:What is MonadBaseControl for?MonadBaseControl 有什么用?
【发布时间】:2012-07-27 19:17:21
【问题描述】:

我正在深入研究 Yesod 的 monad,并且遇到了 MonadBaseControl。 我看了一下hackage doc,然后迷路了。有人能告诉我它试图解决的问题吗?

【问题讨论】:

  • 它实际上来自monad-control,那里的包描述说“这个包定义了类型类 MonadBaseControl,它是 MonadBase 的一个子集,可以从 IO 或任何其他基础中提取诸如 catch 之类的通用控制操作单子。”不幸的是,它没有告诉我它要解决哪个问题。
  • 看看 [lifted-base](hackage.haskell.org/package/lifted-base)。它提供了许多基于IO 的标准函数的提升版本。例如,使用MonadBaseControl,您可以编写一段代码,在基于IO 的复杂monad 堆栈中运行,并在该堆栈中调用fork,将monad 具有的任何上下文也传输到分叉线程中。
  • 一位同事写了一个非常好的介绍和演练:lexi-lambda.github.io/blog/2019/09/07/…

标签: haskell monads


【解决方案1】:

Michael Snoyman 实际上写了一个关于 monad-control 的小教程:http://www.yesodweb.com/book/monad-control

那篇文章的要点可能如下:

想象一下你有这段代码:

withMyFile :: (Handle -> IO a) -> IO a
withMyFile = withFile "test.txt" WriteMode

您可以将withMyFile 应用于Handle -> IO a 类型的任何函数,并获得一个不错的IO a 值。但是,如果你有一个Handle -> ErrorT MyError IO a 类型的函数并且想要获得ErrorT MyError IO a 类型的值怎么办?好吧,基本上,您必须修改withMyFile 才能合并很多包装/展开。 MonadBaseControl 允许您将 withMyFile 之类的函数“提升”到某些允许展开(“运行”)的 monad 转换器。因此,生成的代码如下所示:

useMyFileError :: (Handle -> ErrorT MyError IO ()) -> ErrorT MyError IO ()
useMyFileError func = control $ \run -> withMyFile $ run . func

【讨论】:

    【解决方案2】:

    它来自包monad-control,是一对类型类之一(另一个是MonadTransControl),通过支持替代liftBase( resp. lift) 对实现它的 monad 的操作。这个增强版本不再在绝对基础 monad(即直接基础 monad)中采取简单的操作,而是采用一个函数,在该点获取基础 monad(或 monad 转换器)的整个状态作为其唯一参数并返回上述操作。

    正如包文档所述,此增强功能以​​及这些类型类的其余内容允许您从绝对基础 monad(resp.直接基 monad),这对于 MonadBase (resp. MonadTrans) 中存在的更简单的方案是不可能的,因为后者不允许您解除函数的 arguments,只是结果,而monad-control 采用的方法允许两者兼有。

    因此,可以与MonadBaseControl(或MonadTransControl)一起使用的单子集(分别是单子转换器)是可与MonadBase(分别是MonadTrans),但出于同样的原因,前者比后者强大得多。

    【讨论】:

      猜你喜欢
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-24
      • 2021-09-21
      • 1970-01-01
      • 2017-04-10
      • 1970-01-01
      相关资源
      最近更新 更多