<**> 是 <*> 的变体,参数相反。 "reversed" 是什么意思?
<**> is a variant of <*> with the arguments reversed. What does "reversed" mean?
In GHC.Base
the description of <**>
runs:
A variant of <*>
with the arguments reversed.
众所周知,这种情况下的“反转”并不意味着“翻转”,因为:
GHCi> [1, 2, 3] <**> [(^2), (+1)]
[1,2,4,3,9,4]
GHCi> [(^2), (+1)] <*> [1, 2, 3]
[1,4,9,2,3,4]
那么,“反转”是什么意思?
旁注:有些应用函子具有 (<**>) = flip (<*>)
。例如,这是我对 reader ((->) e
) 的证明:
(->) e: f <**> g =
= liftA2 (flip ($)) f g =
= (flip ($) <$> f) <*> g =
= \e -> ((flip ($) . f) e) (g e) =
= \e -> flip ($) (f e) $ (g e) =
= \e -> (g e) $ (f e) =
= \e -> g e (f e) =
= g <*> f. => (<**>) = flip (<*>).
一种象征性地说明它的方法是根据 liftA2
:
来比较它们的表达式
(<*>) = liftA2 (\f x -> f x)
(<**>) = liftA2 (\x f -> f x)
= liftA2 (flip (\f x -> f x))
如果我们停留在列表的示例上,我们可以通过您的示例看到 <**>
的行为如何相反。
表达式 as <**> fs
的意思类似于
foreach a in as {
foreach f in fs {
add (f a) to result;
}
}
和fs <*> as
的意思是
foreach f in fs {
foreach a in as {
add (f a) to result
}
}
所以 as <**> fs
结果是 [f1(a1), f2(a1), ..., fn(a1), f1(a2), ..., fn(a2), ...]
和fs <*> as
导致[f1(a1), f1(a2), ... , f1(am), f2(a1), ...]
所以循环的顺序是相反的。
我最近添加了 do
-notation to the base documentation,这使得比较 <*>
和 <**>
变得更容易,请注意它们都是 运行 从左到右,并且它们都是return f a
:
fs <*> as
=
do f <- fs
a <- as
pure (f a)
和
as <**> fs
=
do a <- as
f <- fs
pure (f a)
众所周知 codified (Control.Applicative.Backwards
) 应用程序可以 运行 向后,我不得不缩短这个答案。 Li-yao Xia 的答案是 liftA2 ($) 和 liftA2 (&)
In GHC.Base
the description of <**>
runs:
A variant of
<*>
with the arguments reversed.
众所周知,这种情况下的“反转”并不意味着“翻转”,因为:
GHCi> [1, 2, 3] <**> [(^2), (+1)]
[1,2,4,3,9,4]
GHCi> [(^2), (+1)] <*> [1, 2, 3]
[1,4,9,2,3,4]
那么,“反转”是什么意思?
旁注:有些应用函子具有 (<**>) = flip (<*>)
。例如,这是我对 reader ((->) e
) 的证明:
(->) e: f <**> g =
= liftA2 (flip ($)) f g =
= (flip ($) <$> f) <*> g =
= \e -> ((flip ($) . f) e) (g e) =
= \e -> flip ($) (f e) $ (g e) =
= \e -> (g e) $ (f e) =
= \e -> g e (f e) =
= g <*> f. => (<**>) = flip (<*>).
一种象征性地说明它的方法是根据 liftA2
:
(<*>) = liftA2 (\f x -> f x)
(<**>) = liftA2 (\x f -> f x)
= liftA2 (flip (\f x -> f x))
如果我们停留在列表的示例上,我们可以通过您的示例看到 <**>
的行为如何相反。
表达式 as <**> fs
的意思类似于
foreach a in as {
foreach f in fs {
add (f a) to result;
}
}
和fs <*> as
的意思是
foreach f in fs {
foreach a in as {
add (f a) to result
}
}
所以 as <**> fs
结果是 [f1(a1), f2(a1), ..., fn(a1), f1(a2), ..., fn(a2), ...]
和fs <*> as
导致[f1(a1), f1(a2), ... , f1(am), f2(a1), ...]
所以循环的顺序是相反的。
我最近添加了 do
-notation to the base documentation,这使得比较 <*>
和 <**>
变得更容易,请注意它们都是 运行 从左到右,并且它们都是return f a
:
fs <*> as
=
do f <- fs
a <- as
pure (f a)
和
as <**> fs
=
do a <- as
f <- fs
pure (f a)
众所周知 codified (Control.Applicative.Backwards
) 应用程序可以 运行 向后,我不得不缩短这个答案。 Li-yao Xia 的答案是 liftA2 ($) 和 liftA2 (&)