The standard class hierarchy is a consequence of Haskell's historical development, rather than logic.
This article attempts to document various suggestions that have been brought up over the years, along with arguments for and against.
- 1 Make Applicative a superclass of Monad
- 2 Add join as a method of Monad
- 3 Remove liftM, ap, etc. in favor of their Applicative counterparts
- 4 Split fail into its own class
- 5 Rename fmap to map
- 6 Export Applicative in the Prelude
- 7 Redefine >> in terms of *> rather than >>=
- 8 Add a Pointed class
- 9 Related proposals
Applicative a superclass of
class Applicative m => Monad m where ...
- Code that is polymorphic over the Monad can use Applicative operators rather than the ugly
- Most types that implement Monad also implement Applicative already. This change will only make explicit a current best practice.
- Monad is part of standard Haskell, but Applicative is not. If Monad is made a subclass of Applicative, then we will need to add Applicative to the language standard.
- Some libraries, such as blaze-markup, only implement Monad for its do-notation. For these types, an Applicative instance would have no meaning.
join as a method of
class Applicative m => Monad m where (>>=) :: (a -> m b) -> m a -> m b join :: m (m a) -> m a ... m >>= k = join (fmap k m) join m = m >>= id
joinis more orthogonal than
>>=, and the former is closer to the categorical definition.
joinis often easier to implement. See .
- The analogous comonad package is written this way.
>>=is used much more frequently in real-world code than
- Performance: The default implementation of
>>=requires two traversals. Any container-like type which only implements
joinwould be slower.
ap, etc. in favor of their Applicative counterparts
- We will end up with a simpler base library.
- A lot of code will be broken by this change. There is no compelling reason to remove these functions outright, rather than gradually deprecating them as with
- A common pattern is to write a full instance of Monad, then set
fmap = liftMand
(<*>) = ap.
fail into its own class
class Monad m => MonadFail m where fail :: String -> m a
Applicative in the Prelude
>> in terms of
*> rather than
class Pointed p where point :: a -> p a
This is already implemented in the pointed package.
- This class has seen little real-world use. On Hackage, there are only 9 reverse dependencies for
pointed, most of which are by the same author.
- From early 2011: GHC ticket – Makes Applicative into a superclass of Monad, but does not deprecate any existing names
- See  for the associated discussion.
- The Other Prelude