Indeed it does:
λ :i Applicative
class Functor f => Applicative (f :: * -> *) where
At the same time:
fmap f x = pure f <*> x
— by the laws of Applicative
we can define fmap
from pure
& <*>
.
I don't get why I should tediously define fmap
every time I want an Applicative
if, really, fmap
can be automatically set up in terms of pure
and <*>
.
I gather it would be necessary if pure
or <*>
were somehow dependent on the definition of fmap
but I fail to see why they have to.
While there are proposals to make it's easier https://ghc.haskell.org/trac/ghc/wiki/IntrinsicSuperclasses the "default instances" problem itself is very difficult.
One challenge is how to deal with common superclasses:
fmap f x = pure f <*> x -- using Applicative
fmap f x = runIdentity (traverse (Identity . f) x) -- using Traversable
fmap f x = x >>= (return . f) -- using Monad
Which one to pick?
So the best we can do now is to provide fmapDefault
(as Data.Traversable
) does; or use pure f <*> x
; or fmapRep
from Data.Functor.Rep
when applicable.