为什么fmap f xs = pure f*xs?

use*_*628 1 haskell applicative

class Functor f => Applicative f where
       pure :: a -> f a
       (<*>) :: f (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

"纯粹"扮演两个角色:
*当你有一个0-ary函数时的退化情况.
*fmap f xs = pure f*xs

我不明白为什么

fmap f xs = pure f <*> xs
Run Code Online (Sandbox Code Playgroud)

我的意思是pure应该采取任何a回报f a.但是做了pure f什么?甚至pure (f <*> xs)对我有意义.

Jon*_*rdy 8

也许一个具体的例子是说明性的.列出适用的列表.<*>将左操作数中的每个函数应用于右边的每个值:

fs <*> xs = [f x | f <- fs, x <- xs]
Run Code Online (Sandbox Code Playgroud)

pure在单个列表中包含一个值:

pure (+ 1) = [(+ 1)]
Run Code Online (Sandbox Code Playgroud)

所以pure f <*> xs= fmap f xs,因为<*>每个值应用每个函数- 每个值只有一个 - 同时对每个值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]
Run Code Online (Sandbox Code Playgroud)

这也是<$><*>运算符一起工作以在多个动作的结果上应用多参数函数的方式,例如:

(*) <$> [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
]
Run Code Online (Sandbox Code Playgroud)

这也可以写成pure (*) <*> [1..5] <*> [1..5].

<$>构建一个动作(在本例中为一个列表)返回(包含)部分应用的函数,并<*>获取这些函数并将它们应用于参数.(如果函数有两个以上的参数,那么这也可能导致部分应用的函数,可以应用于另一个应用程序的更多参数<*>.)

同样的法律持有其他"集装箱式" applicatives如MaybeEither e(一些e),以及"动作类" applicatives如IO,Cont rAsync.