Haskell 学习笔记四:Applicative
Applicative 这玩意说起来复杂,其实和 Functor 也差不多,都是一种 typeclass。
祖师爷 Dijkstra 曾经说过:
A formula is worth a thousand pictures
很多东西嘛,用文字表达真的麻烦,看看声明就懂了:
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
第一行:Applicative 是一种 Functor。一个 typeclass 要成为一个 Applicative,它必须首先是一个 Functor。
第二行:Applicative 必须实现 pure
函数。它的参数是任何东西(值或者函数都可以),输出是一个装着这个参数的默认的盒子。
第三行:Applicative 必须实现 <*>
函数。第一个输入是【装着函数的盒子】(wrapped function),第二个输入是一个 wrapped value。
听起来可能会很复杂,但是最重要的就是:函数本身也是可以被装进盒子的(上次讲过了)。<*>
接受的第一个参数就是一个 a -> b
函数的盒子。
举个例子:
Prelude> Just (+1) <*> Just (1)
Just 2
Maybe
是一个 Applicative。通过 <*>
,我们可以把一个函数的包裹和另一个值的包裹串起来。
我们再来看看 Maybe
的实现代码:
instance Applicative Maybe where
pure = Just
Just f <*> m = fmap f m
Nothing <*> _m = Nothing
pure
作为最基本最简单的【装进盒子】操作,当然是直接等同于 Just
了。<*>
也很简单,把 f
拿出来,用上次讲过的 fmap
串一串。出来的也是一个 wrapped value(不要忘了 Applicative 必须是 Functor)。
非常简洁优雅。有了 Applicative,你就可以这样:
Prelude> (+) <$> (Just 1) <*> (Just 2)
Just 3
相对比没有用 Applicative 的版本:
Prelude> (+) 1 2
3
完 全 一 致,把一个普通的函数用在 Applicative 上实在是非常简单。