OCaml 中的 monad 有什么用?

What is the use of monads in OCaml?

这可能是一个愚蠢的问题,但由于 OCaml 不是纯粹的并且内置了副作用,那么 OCaml 中的 monad 有什么用?

这可能比您想要的答案要幼稚得多,但 monad 只是一个简单的抽象,可用于构建计算。这是一个像等价关系这样的小数学问题(或者对于比我聪明的人来说,比如一个群体)。一旦你了解了它们是什么,你就会发现它们无处不在,它们有助于组织你的思维。

Monads 与纯度无关,除了没有 Monads 的纯语言几乎完全没用。

通俗地说,Monad 只是一组描述如何执行一系列步骤的规则。拥有 Monad 抽象使您能够定义用于执行内容的 DSL。可以构建一个 Monad 来智能地处理诸如异常、ATOMIC rollbacks/commits、重试逻辑、在每个步骤之间休眠等事情。

这里有一些 Monad 的例子:

https://wiki.haskell.org/Monad#Interesting_monads

我知道这个列表是针对 Haskell 的,它是一门纯语言,但不要因此而混淆。

你不需要理解范畴论来理解什么是 Monad,这与普遍的看法相反。一个 monad 基本上有两件事:(转述自 this wikipedia article

  1. 一个单元函数,定义为 (a -> M a),在 Haskell 中称为 "return",用于将值放入 M​​onad 的上下文中。

  2. 一个绑定操作,定义为(M t -> (t -> M u) -> M u),看起来很吓人,但仔细看,这是一个被调用的函数在流程的每个步骤之间,这是您注入好东西的地方。

根据语言的不同,可能会有更多的东西,但这是它的核心。

虽然 OCaml 允许编写命令式代码,但它本质上仍然是函数式的,它被函数式程序员使用。我们更愿意尽可能使用持久数据结构和算法。

关于你的问题,特别是单子对于异步计算很有用,例如LwtAsync,它们用于绑定计算(而不是通常的设置方式回调)。此外,monad 用于错误处理,而不是异常。此外,monad 在编写解析器方面非常有帮助,请参阅 mparser 库。还有其他用途,我只列举了最流行的。

一般来说,monad 只允许您在简单的顺序语法下隐藏复杂的控制流。

虽然 OCaml 支持大多数语言提供的标准副作用,但这并不包括所有可能的副作用。 OCaml 不提供对许多效果的原生支持。这些效果中的许多都可以使用 Monad 进行编码。例如,

  • 并发(参见 Lwt 和 Async 库)
  • 非确定性选择
  • 第一个-class个后续
  • 矛盾的选择与回溯

使用更复杂的计算表示,例如参数化单子,甚至可以编码更奇特的效果。例如,

  • 多态
  • 线性资源