[英]Why fmap f xs = pure f <*> xs?
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
"pure" plays two roles:
“纯”扮演两个角色:
* The degenerate case when you have a 0-ary function, kind of.*具有0元函数时的简并情况。
* fmap f xs = pure f <*> xs* fmap f xs =纯f <*> xs
I don't understand why 我不明白为什么
fmap f xs = pure f <*> xs
I mean pure
should take any a
and return fa
. 我的意思是
pure
应该取a
并返回fa
。 But what does pure f
do? 但是
pure f
做什么? Even pure (f <*> xs)
makes sense to me. 甚至
pure (f <*> xs)
对我来说也是有意义的。
Maybe a concrete example would be illustrative. 也许一个具体的例子是说明性的。 Take the list applicative.
以适用列表为准。
<*>
applies each function from its left operand to each value from its right: <*>
将每个函数从其左侧操作数应用于其右侧的每个值:
fs <*> xs = [f x | f <- fs, x <- xs]
And pure
wraps a value in a singleton list: pure
将值包装在单例列表中:
pure (+ 1) = [(+ 1)]
So pure f <*> xs
= fmap f xs
, because <*>
applies each function— of which there happens to be only one —to each value, while fmap
applies one function to each value: 因此,
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]
This is also how the <$>
and <*>
operators work together to apply a multi-argument function over the results of multiple actions, eg: 这也是
<$>
和<*>
运算符如何共同作用,以对多个操作的结果应用多参数函数,例如:
(*) <$> [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
]
This could also have been written pure (*) <*> [1..5] <*> [1..5]
. 也可以将其写为
pure (*) <*> [1..5] <*> [1..5]
。
<$>
builds an action (in this case a list) returning (containing) partially applied functions, and <*>
takes those functions and applies them to arguments. <$>
建立一个操作(在本例中为列表),该操作返回(包含)部分应用的函数,而<*>
接受这些函数并将其应用于参数。 (And if the function takes more than two arguments, then this may also result in partially applied functions, which can be applied to more arguments with another application of <*>
.) (并且,如果函数接受两个以上的参数,那么这还可能导致部分应用的函数,而该函数可以通过
<*>
另一个应用程序应用于更多的参数。)
The same laws hold in other “container-like” applicatives such as Maybe
or Either e
(for some e
), as well as “action-like” applicatives such as IO
, Cont r
, or Async
. 其他“类似容器的”应用程序(例如
Maybe
或Either e
(对于某些e
))以及“类似动作”的应用程序(例如IO
, Cont r
或Async
。
But what does
pure f
do?但是
pure f
做什么?
Given, f :: a -> b
, we obtain pure f :: f (a -> b)
the last f
being any applicative functor. 给定
f :: a -> b
,我们得到pure f :: f (a -> b)
,最后一个f
是任何应用函子。 This creates a value of the right type to pass as the first argument to 这将创建一个正确类型的值作为第一个参数传递给
(<*>) :: f (a -> b) -> f a -> f b
I mean
pure
should take anya
and returnfa
我的意思是说
pure
应该取a
并返回fa
Exactly -- in this case the a
you mention is the function type a -> b
I mentioned above. 没错-在这种情况下,
a
你提到的是函数类型a -> b
我上面提到的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.