Default superclass instances

A matter of much consternation, here is a proposal to allow type class declarations to include default instance declarations for their superclasses. It's based on ​Jón Fairbairn's proposal, but it has a more explicit 'off switch' and the policy on corner-cases is rejection. Credit is due also to the ​class system extension proposal and its ancestors, in particular, John Meacham's ​class alias proposal.

We may distinguish two uses of superclasses (not necessarily exclusive).

A class can widen its superclass, extending its interface with new functionality (e.g., adding an inverse to a monoid to obtain a group -- inversion seldom provides an implementation of composition). The subclass methods provide extra functionality, but do not induce a standard implementation of the superclass. Num provides arithmetic operations, widening Eq, but does not induce an implementation of (==).

A class can deepen its superclass, providing methods at least as expressive, admitting a default implementation of superclass functionality (e.g., the compare function from an Ord instance can be used to give an Eq instance; traverse from Traversable f can be instantiated to foldMapDefault for Foldable f and fmapDefault for Functor f).

(SLPJ I don't understand this distinction clearly.)

This
proposal concerns the latter phenomenon, which is currently such a
nuisance that Functor and Applicative are not superclasses of
Monad. Nobody wants to be forced to write Functor and Applicative
instances, just to access the Monad interface. Moreover, any proposal
to refine the library by splitting a type class into depth-layers is
(rightly!) greeted with howls of protest as an absence of superclass
instances gives rise to breakage of the existing codebase.

Default superclass instances are implemented in the
​Strathclyde Haskell Enhancement.
They should enable some tidying of
the library, with relatively few tears. Moreover, they should allow us
to deepen type class hierarchies as we learn. Retaining backward
compatibility in relative silence is the motivation for an opt-in
default.

The proposal

Concretely, the proposal is as follows.

Default superclass instances

First, we allow a class declaration to include a default superclass instance delcaration for some, none, or all of its superclass constraints. We say that superclasses with default implementations are intrinsic superclasses. Example:

Note the instance declaration nested inside the class declaration. This is the default superclass instance declaration, and Functor thereby becomes an intrisic superclass of Applicative. Moreover, note that the definition of fmap uses the <*> operation of Applicative; that is the whole point!

Instance declarations

A default superclass instance in a class declaration for class C
has an effect on the instance declarations for C.

Specifically:

An instance declaration

instance Q => C ty where ...defs...

for class C generates an extra instance
declaration

instance Q => Si ty where ....

for each intrinsic superclass Si of C

The method definitions in ...defs... are distributed to the
appropriate instance declaration, according to which class
the method belongs to.

Any methods that are not specified explicitly are "filled in"
from the default definition given in the default superclass instance.
(If there is no default definition, then a warning is produced,
and a definition that calls error is used instead.)

For example, assume the class declaration for Monad above. Then
this instance declaration:

instance Monad m where
(>>=) = ...blah...
(<*) = ...bleh...

would generate an extra instance declaration for the instrinsic superclass Applicative,
with the methods distributed appropriately:

Note that Functor is only an indirect intrinsic superclass of Monad, via Applicative.
So the above instance would generate an intrinsic instance for Applicative but not for Functor.

Jón's proposal had a more subtle opt-out policy, namely that an
intrinsic superclass can be quietly pre-empted by an instance for the
superclass from a prior or the present module. Note that to declare an
instance of the subclass, one must produce an instance of the
superclass by the same module at the latest.

This quiet exclusion
policy is not enough to handle the case of multiple candidate
intrinsic instances arising from multiple intrinsic superclasses (e.g.,
Traversable and Monad giving competing Functor instances), so some
explicit form is required. The question for us, then, is what should
happen if an intrinsic superclass not explicitly hidden were to clash
with an explicit instance from the same or a prior module. We could

Reject this as a duplicate instance declaration, which indeed it is.

Allow the explicit to supersede the intrinsic default, but issue a warning suggesting to either remove the explicit instance or add an explicit opt-out, or

Allow the explicit to supersede the intrinsic default silently.

As it stands, we propose option 1 as somehow the principled thing to
do. We acknowledge that it creates an issue with legacy code,
precisely because there are plenty of places where we have written the
full stack of instances, often just doing the obvious default thing:
these should be cleaned up, sooner or later.

Option 3 avoids that
problem but risks perplexity: if I make use of some cool package which
introduces some Foo :: * -> *, I might notice that Foo is
a monad and add a Monad Foo instance in my own code, expecting
the Applicative Foo instance to be generated in concert; to my
horror, I find my code has subtle bugs because the package introduced
a different, non-monadic, Applicative Foo instance which I'm
accidentally using instead. Option 2 is certainly worth considering as
a pragmatic transitional compromise, although the 'transitional' has a
dangerous tendency to be permanent.

Multi-headed instance declarations

While we're about it, to allow multi-headed instance declarations for class-disjoint conjunctions, with the same semantics for constraint duplication and method distribution as for the defaults, so