11

Trying to expand my understanding about symbols in Haskell :

  • ($) : Function Application operator (Allow you to apply arguments over a function)
  • (&) : flipped version of Function Application Operator? (&) = flip ($)
  • (<>) : associative operator (You'll find it in Semigroups and Monoids)
  • (<$>) : function application ($) lifted over a Functor structure
  • (<&>) : flipped functor map

Can we make a link between (*) and (<*>)?

I don't understand the meaning of * actually...

Nicolas Henin
  • 3,244
  • 2
  • 21
  • 42
  • 3
    I don't think there is a link between `*` and `<*>`, I guess `<*>` was chosen for its relation to `<$>`, but I'd say the `*` used here is quite arbitrary. – flawr Apr 04 '19 at 10:23
  • 2
    I don't think the `*` in `<*>` is meaningful. Function names `<$>` and `<&>` are clearly taken from `$` and `&`. However, `<*>` is incidental. I think the `<` and `>` were chosen so that the idiom `f <$> x <*> y <*> z` looks nice, but the `*` looks arbitrary there. – chi Apr 04 '19 at 10:23
  • 3
    @chi do you have historical notes on that? I don't know for sure whether this was deliberate, but to me the reference to the products in monoidal functors is striking and seems unlikely to be a coincidence. – leftaroundabout Apr 04 '19 at 10:53
  • 1
    @leftaroundabout Mine is only a guess, I have nothing to back me up. I don't know if I agree with you on this point: I would if we had `(<*>) :: 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 Apr 04 '19 at 11:02
  • 2
    @chi see edit to my answer: it **is** derived from products in the original McBride and Paterson paper. – leftaroundabout Apr 04 '19 at 11:25

1 Answers1

16

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 AF BF(AB)

...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, φ.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319