天天看点

Swift函数式编程十三(函子、适用函子、单子)

解释一些函数式编程中的专用术语和一些常⻅模式,比如函子 (Functor)、适用函子 (Applicative Functor) 和单子 (Monad) 等。理解这些常⻅的模式,会有助于设计自己 的数据类型,并为 API 选择更合适的函数。

函子

目前已经遇到了几个被命名为 map 的方法,类型分别如下:

extension Array {
func map<R>(transform: (Element) -> R) -> [R]
}
extension Optional {
func map<R>(transform: (Wrapped) -> R) -> R? }
extension Parser {
func map<T>(_ transform: @escaping (Result) -> T) -> Parser<T>
}
           

每个 map 方法都需要两个参数:一个即将被映射的数据结构,和一个类型为 (T) -> U 的函数 transform。对于数组或可选值参数中所有类型为 T 的值,map 方法会使用 transform 将它们转换为 U。这种支持 map 运算的类型构造体 —— 比如可选值或数组 —— 有时候也被称作函子 (Functor)。

函子也会被描述为一个储存特定类型值的 “容器”。而 map 方法则用来对储存在容器中的值进行转换。

适用函子

除了 map ,许多函子还支持其它的运算。

对于任意的类型构造体,如果可以为其 定义恰当的 pure 与 <*> 运算,就可以将其称之为一个适用函子 (Applicative Functor)。或 者再严谨一些,对任意一个函子 F,如果能支持以下运算,该函子就是一个适用函子:

func pure<A>(_ value: A) -> F<A>
func <*><A, B>(f: F<A -> B>, x: F<A>) -> F<B>
           

单子

如果一个类型构造体 F 定义了下面两个函数,它就是一个单子 (Monad):

func pure<A>(_ value: A) -> F<A>
func flatMap<A, B>(_ f: (A) -> F<B>) -> F<B>