What is the point of the Functor -> Applicative -> Monad hierarchy [duplicate]
Asked Answered
H

2

5

What is the point of making Functor a super class of Applicative and Monad. Both Applicative and Monad immediately imply the only implementation of Functor that abides by the laws as far as I can tell. But rather I have to type out the same implementation of Functor every time. Is there a way to avoid doing this?

Further more Monad implies the only implementation of Applicative that abides by the laws so why make Applicative a super class of Monad? Again it makes implementing Applicative for new data types redundant.

Is there a way to make a Monad without having to implement Applicative and Functor (as its operations are already the most general). And to make an Applicative without having to implement Functor.

I see the benefit of the class hierarchy as what I just said explains the "is a" relation between them. But at the same time having to implement each is annoying. I just want to define return and >>= and get all the operations of all 3 back.

Hipster answered 2/1, 2022 at 7:7 Comment(1)
Related: Why should Applicative be a superclass of Monad?Exam
D
9

You can get those instances this way:

import Control.Applicative
data Whatever a = {- ... -} deriving (Functor, Applicative) via (WrappedMonad Whatever)

It would have been nice to add DefaultSignatures defaults to the Functor and Applicative classes at the time the compiler broke from the spec, so that you wouldn't even need to write via WrappedMonad, but now that it's done I suspect we'll never get them. Too bad.

Dietetic answered 2/1, 2022 at 8:13 Comment(2)
Please don't derive Functor via WrappedMonad. Much better to stock derive it. (And for Applicative it's also always worth considering to implement the instance directly, instead of piggy-backing on the Monad one which may well be less efficient.)Palate
Applicative can't be derived since before deriving via (issue) because they removed return as part of the Monad of No Return. If you try to use pure @Whatever it will diverge!Mercaptide
E
3

The cost of having to write the Applicative and Monad instances is paid only once, by the implementer. The cost of not having those instances, however, is borne by the users, time and time again. Consider a combinator which uses Applicative, such as traverse:

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)

Without the superclass relationship, our choice of f being a Monad wouldn't be enough to let us use traverse. We'd end up needing a Monad-specific version of traverse (that is, mapM), and to switch from one to the other on the grounds of a distinction which is almost always irrelevant. Having Applicative as a superclass of Monad means we need not bother with that.

Exam answered 2/1, 2022 at 13:35 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.