Superclass defaults

Jonas Almström Duregård jonas.duregard at
Fri Sep 2 11:55:39 CEST 2011


On 31 August 2011 12:22, Conor McBride <conor at> wrote:
> I become perplexed very easily. I think we should warn whenever silent
> pre-emption (rather than explicit) hiding is used to suppress a default
> instance, because it is bad --- it makes the meaning of an instance
> declaration rather more context dependent. Perhaps a design principle
> should be that to understand an instance declaration, you need only
> know (in addition) the tower of class declaration s above it: it is
> subtle and worrying to make the meaning of one instance declaration
> depend on the presence or absence of others.

Those are all good arguments, and you've convinced me that always
warning is better.

> Arguably, option 1 does not conflict with design goal 1. Design goal 1
> supports a methodology for refining a class into a hierarchy without
> creating the need for stacks of default instances or breaking code. If
> the new superclass is a brand new thing without legacy instances,
> there's no problem. If we'd had this mechanism in place, Functor would
> always have been made a superclass of Monad, Applicative would have
> been easily inserted, and we wouldn't have the stacks of manually added
> default instances to worry about.
> The main problem with Option 1 is in dealing with the legacy of
> classes which currently require a stack of default instances, creating
> a hierarchy from parts which already exist. Option 1 would create a bunch
> of instance conflicts and thus demand changes to code. Design goal 1
> isn't very explicit (sorry!) about this distinction between introducing
> new classes as superclasses and building hierarchies from legacy classes,
> but it was the former I intended. I always expected the latter to cause
> trouble.
> If it is also a design goal to minimize damage with respect to the
> current unfortunate situation, then Option 1 is problematic. Whatever we
> might wish, we are where we are. We should be pragmatic. I think we
> should set Option 1 as the direction of travel, but go with Option 2 for
> the moment. We should make sure that the warnings generated by Option 2
> are sufficiently informative that it is easy to track down the conflicts
> and resolve them explicitly, for Option 1 compliance.

First of all, I think the design goal is quite clear: "a class C can
be re-factored into a class C with a superclass S, without disturbing
any clients". Requiring client C to opt-out from the default
implementation of S is a clear violation of the design goal. So I
disagree that option 1 can be compatible with the design goal, but
like you say the design goal might be at fault.

Also, if I understand you correctly, you say the current situation is
exceptional, and suggest option 2 as a temporary solution to it. You
seem convinced that these kind of situations will not appear in the
future, but I'm not as optimistic about that.

Even when superclass defaults are implemented, people will
occasionally implement classes without realizing that there is a
suitable intrinsic superclass (or add the superclass but not the
default instance). People will start using the new class and give
separate instances for the superclass, and eventually someone will
point out that the there should be a default instance for the
superclass. Now if option 1 is implemented, the library maintainers
will be reluctant to add the superclass instance because it will break
a lot of client code.

Will there be a solution to this dilemma that I have missed? Should
the client code be allowed opt-out from the superclass preemptively
before it is given a default? Won't that cause a similar perplexity?


More information about the Glasgow-haskell-users mailing list