5. 函子、应用函子与单子
Functor 和 Monad 都描述了针对仍在等待一个类型参数的类型的操作。
理解它们的一种方式是:Functor 描述其中所含数据可以被变换的容器,而 Monad 描述带有副作用的程序的一种编码。
然而,这种理解并不完整。
毕竟,Option 同时具有 Functor 和 Monad 的实例,并且同时表示一个可选值 and 一个可能无法返回值的计算。
从数据结构的角度看,Option 有些像可空类型,或像至多只能包含一个条目的列表。
从控制结构的角度看,Option 表示一种可能在没有结果的情况下提前终止的计算。
通常,使用 Functor 实例的程序最容易被理解为把 Option 用作数据结构,而使用 Monad 实例的程序最容易被理解为使用 Option 来允许提前失败;不过,学会熟练运用这两种视角,是精通函数式编程的重要组成部分。
函子与单子之间存在更深层的关系。
事实证明,每个单子都是函子。
另一种说法是,单子抽象比函子抽象更强大,因为并非每个函子都是单子。
此外,还存在一种额外的中间抽象,称为应用函子,它具有足够的表达能力来编写许多有趣的程序,同时又允许使用无法采用 Monad 接口的库。
类型类 Applicative 提供了应用函子的可重载操作。
每个单子都是应用函子,每个应用函子都是函子,但反过来并不成立。