haskell - IO monad 在什么意义上是特殊的(如果有的话)?

标签 haskell functional-programming monads io-monad

在深入研究 monad 之后,我了解到它们是一个通用概念,允许在某些上下文(失败、非确定性、状态等)内链接计算,并且它们背后没有魔法。

即使不是魔法,但 IO monad 仍然感觉很特别。

  • 你不能像使用其他 monad 一样逃避 IO monad
  • IO 操作只能由 main 运行功能
  • IO 始终位于 monad 转换器链的底部
  • IO monad 的实现不清楚,源代码显示了一些 Haskell 内部

  • 以上几点的原因是什么?是什么让 IO 如此特别?

    更新 :在纯代码评估顺序中并不重要。但是在做 IO 时确实很重要(我们想在阅读之前保存客户)。据我了解,IO monad 为我们提供了这样的排序保证。它是一般 monad 的属性还是 IO monad 特有的属性?

    最佳答案

    you cannot escape IO monad like you can with other monads



    我不确定你所说的“逃跑”是什么意思。如果你的意思是,以某种方式解开一元值的内部表示(例如列表 -> 单元格序列)——这是一个实现细节。其实可以定义an IO emulation in pure Haskell – 基本上只是一个 State通过大量全局可用的数据。这将具有 IO 的所有语义。 ,但没有实际与现实世界交互,只是对其进行模拟。

    如果您的意思是,您可以从 monad 中“提取值”——不,这通常是不可能的,即使对于大多数纯 haskell monad 也是如此。例如,您不能从 Maybe a 中提取值。 (可以是 Nothing )或 Reader b a (如果 b 无人居住怎么办?)

    IO action can only be run by the main function



    嗯,从某种意义上说,一切都只能由main 运行。功能。未以某种方式从 main 调用的代码只会坐在那里,您可以将其替换为 undefined没有改变任何东西。

    IO is always at the bottom of a monad transformers chain



    是的,但对于例如,情况也是如此。 ST .

    Implementation of IO monad is unclear and source code shows some Haskell internals



    再说一遍:实现只是一个实现细节。 IO 的复杂性实现实际上与高度优化有很大关系;对于专门的纯单子(monad)也是如此(例如 attoparsec )。

    As I already said ),更简单的实现是可能的,但它们不会像成熟的优化现实世界 IO 那样有用类型。

    幸运的是,实现并不需要真正打扰您。 IO的内部可能不清楚,但外部,实际的单子(monad)接口(interface),非常简单。

    in pure code evaluation order doesn't matter



    首先——评估顺序在纯代码中很重要!
    Prelude> take 10 $ foldr (\h t -> h `seq` (h:t)) [] [0..]
    [0,1,2,3,4,5,6,7,8,9]
    Prelude> take 10 $ foldr (\h t -> t `seq` (h:t)) [] [0..]
    ^CInterrupted.
    

    但实际上,由于纯代码评估顺序错误,您永远不会得到错误的非⊥结果。这实际上不适用于重新排序一元 Action (IO 或其他),因为更改序列顺序会更改结果 Action 的实际结构,而不仅仅是运行时将用于构造此结构的评估顺序。

    例如(列表单子(monad)):
    Prelude> [1,2,3] >>= \e -> [10,20,30] >>= \z -> [e+z]
    [11,21,31,12,22,32,13,23,33]
    Prelude> [10,20,30] >>= \z -> [1,2,3] >>= \e -> [e+z]
    [11,12,13,21,22,23,31,32,33]
    

    说了这么多,当然IO非常特别,确实我认为有些人不愿称它为 monad(对于 IO 履行 monad 法则的实际含义有点不清楚)。特别是,惰性 IO 是一个巨大的麻烦制造者(最好始终避免)。

    关于haskell - IO monad 在什么意义上是特殊的(如果有的话)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36596701/

    相关文章:

    Haskell LLVM 绑定(bind)模糊类型

    haskell - 使用导出的符号

    scala - 如何以函数式编程风格在 Scala 中创建列表列表

    scala - 关于点菜数据类型的问题

    Haskell:对 `>>=` 运算符的类型感到困惑

    http - 从某些函数调用时,Haskell System.Timeout.timeout崩溃

    javascript - 这是 Javascript 中有效的 monad 转换器吗?

    haskell - 使用 Join() 而不是 Bind() 的 Monad

    haskell - 从 Haskell 中的 do block 返回之前是否可以检查某些条件?

    haskell - 无限循环与IO如何在haskell中工作