This is deliberate. <*>
has characteristics of a tensor product. This is best seen in the list monad:
Prelude> (,) <$> ['a'..'e'] <*> [0..4]
[('a',0),('a',1),('a',2),('a',3),('a',4)
,('b',0),('b',1),('b',2),('b',3),('b',4)
,('c',0),('c',1),('c',2),('c',3),('c',4)
,('d',0),('d',1),('d',2),('d',3),('d',4)
,('e',0),('e',1),('e',2),('e',3),('e',4)]
More generally, applicative functors (aka monoidal functors) map from the product of two objects (i.e. product type, aka tuple or via currying two function arguments) behind the functor to the functor-result of a product before the functor. So it's a pretty product-ey operation indeed.
φA,B: F A ∙ F B → F(A⊗B)
...in Haskell,
φ :: (f a, f b) -> f (a,b)
φ = uncurry (liftA2 (,))
-- recall `liftA2 f x y = f <$> x <*> y`
or even
{-# LANGUAGE TypeOperators #-}
type x ⊗ y = (x,y)
φ :: f a ⊗ f b -> f (a⊗b)
To see the historical side, look into McBride and Paterson 2008 (doi:10.1017/S0956796807006326), the paper that first introduced the Applicative
typeclass. They note
The Applicative class features the asymmetrical operation ⊛
, but there is an equivalent symmetrical definition.
class Functor f -> Monoidal f where
unit :: f ()
(★) :: f a -> f b -> f (a,b)
These operations are clearly definable for any Applicative functor...
So, the <*>
is an ASCII rendition of McBride and Paterson's ⊛
operator, which in turn is an “applicativised” form of ★
which the category theorists call, in uncurried form, φ.
*
and<*>
, I guess<*>
was chosen for its relation to<$>
, but I'd say the*
used here is quite arbitrary. - flawr*
in<*>
is meaningful. Function names<$>
and<&>
are clearly taken from$
and&
. However,<*>
is incidental. I think the<
and>
were chosen so that the idiomf <$> x <*> y <*> z
looks nice, but the*
looks arbitrary there. - chi(<*>) :: Applicative f => f a -> f b -> f (a,b)
. Just because this can be defined in terms of<*>
is not enough to fully convince me. (But you might be right!) - chi