According to the Typeclassopedia (among other sources), Applicative
logically belongs between Monad
and Pointed
(and thus Functor
They can differ, but they shouldn't.
They can differ because they can have different implementations: one is defined in an instance Applicative
while the other is defined in an instance Monad
. But if they indeed differ, then I'd say the programmer who wrote those instances wrote misleading code.
You are right: the functions exist as they do for historical reasons. People have strong ideas about how things should have been.
liftA
, liftM
, fmap
, and .
should all be the same function, and they must be if they satisfy the functor law:
fmap id = id
However, this is not checked by Haskell.
Now for Applicative. It's possible for ap
and <*>
to be distinct for some functors simply because there could be more than one implementation that satisfies the types and the laws. For example, List has more than one possible Applicative
instance. You could declare an applicative as follows:
instance Applicative [] where
(f:fs) <*> (x:xs) = f x : fs <*> xs
_ <*> _ = []
pure = repeat
The ap
function would still be defined as liftM2 id
, which is the Applicative
instance that comes for free with every Monad
. But here you have an example of a type constructor having more than one Applicative
instance, both of which satisfy the laws. But if your monads and your applicative functors disagree, it's considered good form to have different types for them. For example, the Applicative
instance above does not agree with the monad for []
, so you should really say newtype ZipList a = ZipList [a]
and then make the new instance for ZipList
instead of []
.