Introduction Monad介绍

What is a monad? 什么是Monad?

译注:这里的“计算”可以理解为程序,或者说程序会更顺口些,不过原文是computation,含义应与传统的程序相区分,故采用“计算”的翻译。

一个monad是用值和使用这些值的计算序列来构建计算的方法。Monad允许 程序员使用序列的块来构建计算,这些序列的块本身也可以是序列的计算。Monad来决定如何组合这些计算来构建一个新的计算,程序员不需要每次手工编写组合的程序。

可以把monad想象成把计算组合成更复杂的计算的策略。比如,你应该对Haskell中的 Maybe这个类型很熟悉:

data Maybe a = Nothing | Just a

Maybe表示了一种在返回值时有可能会失败的计算类型。返回Maybe类型值得的组合计算暗示了一种策略:如果一个组合的计算包括一个计算B和一个计算A,其中B计算依赖于A计算的结果,如果A或者B返回Nothing,那么组合组合的计算返回Nothing,如果A和B计算都成功,则这个组合计算返回B计算的值。
其他的monad存在于使用I/O的,有状态的,可能返回多个值的等等的计算中。有多少种计算的策略就会有多少种不同类型的monad,不过有一些特殊的monad尤其的有用并且足够通用,他们包含在 Haskell98 标准库中。这些Monad将在本教程的第二部分中分别介绍。

Why should I make the effort to understand monads?

我为什么要努力理解Monad?

网上存在的关于 monad的教程的绝对数量反应了很多人对这个问题的难度大理解。(译注:真的很多,我也看了很多,还是不理解)这是因为monad的抽象实质,以及一些使用它的不同方式,这会造成一副很令人混淆的图景,让人们不清楚究竟Monad是什么,适合干什么。
Haskell中,monad在IO系统里扮演了核心角色。理解haskell中使用monad进行IO并非基本要求,不过理解了IO monad将改进代码并扩展你的能力。
对程序员来说,monad是构建函数式程序的有用工具。他们具有的三个属性使他们特别有用:

  • 模块性:可以使用简单的计算组成复杂的计算,并且将组合策略与实际的计算相隔离。
  • 适应性:使用monad的函数式程序可以比不使用monad的等价程序具有更好地适应性。因为monad把计算的策略提取到一个单独的地方而不是分布在整个程序的各处。
  • 隔离性:可以用来编写命令式风格的程序,并与函数式风格的程序主体安全的隔离。这使得纯函数式的语言如Haskell可以应用“副作用”(如IO)以及状态(状态的使用违反了引用透明性)。

    后面在讲具体的monad时会回头来重新提到这些特性。