函子、应用函子与单子
Functor
和 Monad
都描述了那些仍在等待类型参数的类型的操作。
一种理解它们的方式是,Functor
描述了容器,其中容器内的数据可以被转换,而 Monad
描述了具有副作用的程序编码。
然而,这种理解是不完整的。
毕竟,Option
同时拥有 Functor
和 Monad
的实例,并且同时代表着一个可选值 和 一个可能无法返回值的计算。
从数据结构的角度来看,Option
有点像一个可为空的类型,或者像一个最多可以包含一个条目的列表。
从控制结构的角度来看,Option
代表着一种可能会提前终止而没有结果的计算。
通常,使用 Functor
实例的程序最容易被理解为将 Option
用作数据结构,而使用 Monad
实例的程序则更容易被理解为将 Option
用于支持早期失败,但熟练地掌握这两种视角对于精通函数式编程至关重要。
函子 (Functor) 和 单子 (Monad) 之间有一个更深层次的关系。
事实证明,每个单子都是一个函子。
换句话说,单子抽象 (Monad Abstraction) 比函子抽象 (Functor Abstraction) 更强大,因为不是每个函子都是单子。
此外,还有一个额外的中间抽象,被称为 应用函子 (Applicative Functors),它有足够的能力来编写许多有趣的程序,而且还适用于那些无法使用 Monad
接口的库。
类型类 Applicative
提供了应用函子的可重载操作。
每个单子都是一个应用函子,而每个应用函子也都是一个函子,但反之则不成立。