前段时间学了下 Haskell,看完了《Haskell 趣学指南》,刷了一些题,《Real World Haskell》正在看。因为早先看过《SICP》,有点 FP 的基础,平常写 Swift 也喜欢用些 FP 的技巧,所以暂时没有什么特别颠覆性的感觉。最大的感受是,以前对 Functor、Applicative 和 Monad 的理解太片面了。
Functor
谈 Monad(单子) 之前还是要谈谈 Functor(函子),毕竟所有的 Monad 都是 Functor。在范畴论中,函子是范畴间的一类态射(这个定义给我的直观感受是函子指的是 fmap 函数……),数学上的概念就不多说了,下面我们来看看 Haskell 中的 Functor。
Haskell 中有一个叫 Functor 的类型类(暂时可以粗略地理解为 OO 语言中的接口),它的定义是这样的:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Functor 的实例不是一个具体的类型,而是一个类型构造器(暂时理解为类似范型类的东西),譬如 Int、Maybe Int 都是具体类型,而 Maybe 就是个类型构造器。所以从 Functor 的定义来看,似乎只要实现了 fmap 函数的类型构造器,就是函子了。事实上并不是这样,函子毕竟是一个数学概念,它必须满足函子定律:
fmap id = id
famp (f . g) = fmap f . fmap g
id 是一个原样返回参数的函数(id x = x
),.
表示函数组合(f . g = \x -> f (g x)
)。这两条定律可以保证在一个函子值上执行 fmap 只会在它上面映射一个函数——不再做其他事情。