Applicative Functor允许Functor的链式调用
Applicative Functor
Control.Applicative模块1
2
3class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
pure将一个值包装到一个最简单的(默认或者说最小)环境里
<*>可以使用环境里的函数处理另一个环境
Maybe
1 | instance Applicative Maybe where |
Maybe Applicative 链式调用
1 | (<$>) :: (Functor f) => (a -> b) -> f a -> f b |
这种方式使我们不需要理会环境,直接处理环境内的值
List
1 | instance Applicative [] where |
1 | ghci> [(+),(*)] <*> [1,2] <*> [3,4] |
使用applicative style取代list comprehension1
2
3
4ghci> [ x*y | x <- [2,5,10], y <- [8,10,11]]
[16,20,22,40,50,55,80,100,110]
ghci> (*) <$> [2,5,10] <*> [8,10,11]
[16,20,22,40,50,55,80,100,110]
这里好像可以得出这样一个结论,
那就是Haskell在尽可能地消除变量
上面的例子里x,y都没有了,只有行为和数据
IO也是applicative functor
function也是applicative functor
1 | instance Applicative ((->) r) where |
1 | ghci> (+) <$> (+3) <*> (*100) $ 5 |
1 | ghci> (\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5 |
<\$>左边的得是一个二(N,右边有N个一元函数的情况)元函数,即函数的函数,即函数在一个环境(这个环境恰好也是一个函数)里
每执行一个<$>或<*>就减一元,到最后只剩一元(即前面的几个函数合成成的新函数,根据curry化,一元就是N元)
最后接受一个参数可得结果,
所以function使用applicative的效果依然是类似function composition
本以为函数的applicative会定义成这样1
2
3instance Applicative ((->) r) where
pure x = (\_ -> x)
f <*> g = \x y -> f x (g y)
这样元数不会减少, 但是就只对二元函数有用了,
不如官方的定义有用吧
<*>的意义是将f这个functor(恰好也是个function)里的function取出来修饰g这个一元函数(也是functor)
到此为止吧,我也没完全明白
ZipList as Applicative Functor
1 | instance Applicative ZipList where |
这里的ZipList可以取代zipWithN函数
getZipList函数用来从ZipList取出List
Applicative法则
1 | pure f <*> x = fmap f x |
liftA2
1 | liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c |
With ordinary functors, we can just map functions over one functor value.
With applicative functors, we can apply a function between several functor values.
我们可以实现这样一个函数,把Applicative值都拼到一个List里1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17sequenceA :: (Applicative f) => [f a] -> f [a]
sequenceA [] = pure []
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
ghci> sequenceA [(+3),(+2),(+1)] 3
ghci> (\x y z -> [x,y,z]) <$> (+3) <*> (+2) <*> (+1) $ 3
[6,5,4]
ghci> map (\f -> f 7) [(>4),(<10),odd]
[True,True,True]
ghci> and $ map (\f -> f 7) [(>4),(<10),odd]
True
可以改写成
ghci> sequenceA [(>4),(<10),odd] 7
[True,True,True]
ghci> and $ sequenceA [(>4),(<10),odd] 7
True