Well, I’m not terribly satisfied with the answers given so far, but I think the comments attached to them are a bit more compelling. So I’ll summarize here:
I think there’s only one sensible Functor
instance that follows from Applicative
:
fmap f fa = pure f <*> fa
Assuming that’s unique, it makes sense that Functor
should be a superclass of Applicative
, with that law. Likewise, I think there’s only one sensible Functor
instance that follows from Monad
:
fmap f fa = fa >>= return . f
So again, it makes sense that Functor
should be a superclass of Monad
. The objection I had (and, really, still have) is that there are two sensible Applicative
instances that follow from Monad
and, in some specific instances, even more that are lawful; so why mandate one?
pigworker (first author on the original Applicative
paper) writes:
“Of course it doesn’t follow. It’s a choice.”
(on twitter): “do-notation is unjust punishment for working in a monad; we deserve applicative notation”
duplode similarly writes:
“… it is fair to say that
pure === return
and(<*>) === ap
aren’t laws in the strong sense that e.g. the monad laws are so …”“On the
LeftA
/RightA
idea: there are comparable cases elsewhere in the standard libraries (e.g.Sum
andProduct
inData.Monoid
). The problem of doing the same withApplicative
is that the power-to-weight relation is too low to justify the extra precision/flexibility. The newtypes would make applicative style a lot less pleasant to use.”
So, I’m happy to see that choice stated explicitly, justified by the simple reasoning that it makes the most common cases easier.