为什么fmap f xs =纯f <*> xs?

时间:2018-08-11 22:53:12

标签: haskell applicative

class Functor f => Applicative f where
       pure :: a -> f a
       (<*>) :: f (a -> b) -> f a -> f b
  

“纯”扮演两个角色:
  *简并情况   0元函数,一种。
  * fmap f xs =纯f <*> xs

我不明白为什么

fmap f xs = pure f <*> xs

我的意思是pure应该取任何a并返回f a。但是pure f的作用是什么?甚至pure (f <*> xs)对我也有意义。

2 个答案:

答案 0 :(得分:8)

也许一个具体的例子是说明性的。以适用列表为准。 <*> each 函数从其左侧操作数应用于其 each 从其右侧的值:

fs <*> xs = [f x | f <- fs, x <- xs]

然后pure将一个值包装在一个单例列表中:

pure (+ 1) = [(+ 1)]

所以pure f <*> xs = fmap f xs,因为<*>将每个函数(碰巧只有一个)应用于每个值,而{{1 }}将一个函数应用于每个值:

fmap

这也是pure (+ 1) <*> [1, 2, 3] = [(+ 1)] <*> [1, 2, 3] = [f x | f <- [(+ 1)], x <- [1, 2, 3]] = [(+ 1) x | x <- 1, 2, 3] = [x + 1 | x <- 1, 2, 3] = [2, 3, 4] fmap (+ 1) [1, 2, 3] = [(+ 1) x | x <- [1, 2, 3]] = [x + 1 | x <- [1, 2, 3]] = [2, 3, 4] <$>运算符如何共同为多个操作的结果应用多参数函数的方法,例如:

<*>

这也可以写成(*) <$> [1..5] <*> [1..5] = ((*) <$> [1..5]) <*> [1..5] = [(1 *), (2 *), (3 *), (4 *), (5 *)] <*> [1..5] = [ (1 *) 1, (2 *) 1, (3 *) 1, (4 *) 1, (5 *) 1 , (1 *) 2, (2 *) 2, (3 *) 2, (4 *) 2, (5 *) 2 , (1 *) 3, (2 *) 3, (3 *) 3, (4 *) 3, (5 *) 3 , (1 *) 4, (2 *) 4, (3 *) 4, (4 *) 4, (5 *) 4 , (1 *) 5, (2 *) 5, (3 *) 5, (4 *) 5, (5 *) 5 ] = [ 1, 2, 3, 4, 5 , 2, 4, 6, 8, 10 , 3, 6, 9, 12, 15 , 4, 8, 12, 16, 20 , 5, 10, 15, 20, 25 ]

pure (*) <*> [1..5] <*> [1..5]构建一个操作(在本例中为列表),该操作返回(包含)部分应用的功能,而<$>接受这些功能并将其应用于参数。 (而且,如果该函数接受两个以上的参数,则这也可能会导致部分应用的函数,可以使用<*>的另一个应用程序将其应用于更多的参数。)

相同的法律在<*>Maybe(对于某些Either e)等“类似容器”的应用程序中以及{ {1}},eIO

答案 1 :(得分:2)

  

但是pure f是做什么的?

给出f :: a -> b,我们获得pure f :: f (a -> b),最后一个f是任何应用函子。这将创建正确类型的值作为第一个参数传递给

(<*>) :: f (a -> b) -> f a -> f b
  

我的意思是pure应该取任何a并返回f a

是的-在这种情况下,您提到的a是我上面提到的函数类型a -> b