是否有正当理由在IO之上构建monad变压器堆栈?

时间:2018-09-29 13:13:37

标签: haskell io monads

IO在Haskell中比较棘手。线程,FFI,异步异常,懒惰,您都可以命名。

然后我们有MonadIO,它允许在底部有IO的Monadic堆栈分层。由于IO动作可以执行任意操作,因此在这种不稳定的基础之上构建monadic堆栈有什么价值?

为什么存在?如果您确实需要执行任意副作用,为什么不构建自定义monad IO

3 个答案:

答案 0 :(得分:2)

如今,使用the ReaderT design pattern是一种常见的方法。

您警惕将其他变压器置于IO之上,上面链接的博客文章解释了其中的某些原因。

但是,在将“通用应用程序配置”传递给所有功能时,ReaderT却提供了一些便利。

答案 1 :(得分:1)

  

在这种摇摇欲坠的顶部建立单子堆栈的价值是什么   基础?

IO上方的变形金刚可以让您更方便地谈论重复动作的序列(因此various streaming libraries)。

他们还可以帮助进行externally allocated resources的簿记。

IO的“野性”并不是将变压器堆叠在顶部的普遍反对意见,因为它们可以帮助您避免重复的代码并使基本逻辑更清晰。

相反,argumentIO已经提供了一些内置功能来处理错误(exceptions)和可变引用(IORef s,{{3} } ...),因此为已经存在的功能添加转换器可能会过大。

尤其是可变引用的一个论据是,“纯”所维持的状态意味着在弹出异常时消失,而这可能不是您想要的。您还可以从多个线程访问可变引用。

答案 2 :(得分:1)

在为不是MonadIO实例的 类型的类型实现函数时,

MonadIO可能会很有用。

newtype FooMonad a
  = FooMonad (StateT Int IO a)
  deriving (Functor, Applicative, Monad)

doFoo :: FooMonad String
doFoo = FooMonad $ liftIO getLine

您可以使用MonadIOStateT Int的{​​{1}}实例方便地定义“原始” IO动作。其他使用模块的用户仅限于您选择导出的基元。