In GHC.Base
the description of <**>
runs:
A variant of
<*>
with the arguments reversed.
It is widely known that "reversed" in that case does not mean "flipped" as:
GHCi> [1, 2, 3] <**> [(^2), (+1)]
[1,2,4,3,9,4]
GHCi> [(^2), (+1)] <*> [1, 2, 3]
[1,4,9,2,3,4]
So, what does "reversed" mean?
Side note: there are applicative functors which have (<**>) = flip (<*>)
. For example, here is my proof for the 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 (<*>).
Python reversed() The reversed() method computes the reverse of a given sequence object and returns it in the form of a list.
foo. reverse() actually reverses the elements in the container. reversed() doesn't actually reverse anything, it merely returns an object that can be used to iterate over the container's elements in reverse order. If that's what you need, it's often faster than actually reversing the elements.
The reverse method transposes the elements of the calling array object in place, mutating the array, and returning a reference to the array. reverse is intentionally generic; this method can be called or applied to objects resembling arrays.
std::reverse() in C++ reverse() is a predefined function in header file algorithm. It is defined as a template in the above mentioned header file. It reverses the order of the elements in the range [first, last) of any container.
I recently added do
-notation to the base documentation which makes it easier to compare <*>
and <**>
, notice how both of them run left-to-right and both of them return f a
:
fs <*> as
=
do f <- fs
a <- as
pure (f a)
and
as <**> fs
=
do a <- as
f <- fs
pure (f a)
It is known and codified (Control.Applicative.Backwards
) that applicatives can be run backwards , I have to cut this answer short. Li-yao Xia's answer with liftA2 ($) and liftA2 (&)
One way to illustrate it symbolically is to compare their expressions in terms of liftA2
:
(<*>) = liftA2 (\f x -> f x)
(<**>) = liftA2 (\x f -> f x)
= liftA2 (flip (\f x -> f x))
If we stay at the example of lists we can see through your examples how <**>
behaves reverse.
The expression as <**> fs
means something like
foreach a in as {
foreach f in fs {
add (f a) to result;
}
}
and fs <*> as
means something like
foreach f in fs {
foreach a in as {
add (f a) to result
}
}
So as <**> fs
results in [f1(a1), f2(a1), ..., fn(a1), f1(a2), ..., fn(a2), ...]
And fs <*> as
result in [f1(a1), f1(a2), ... , f1(am), f2(a1), ...]
So the order of the loops is reversed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With