Superclass defaults

From HaskellWiki
Jump to navigation Jump to search

John Meacham's class alias proposal conflates two different issues:

  • Class aliases: A single name for multiple classes.
  • Method defaults in aliases: Allow defaults across classes.

I think it would be better to separate the two.

In particular, we would like Monad to have a default implementation of Functor's fmap. In John's propsal this is not possible, you need a new Monad_ class alias which contains the default.

Superclass defaults

  1. A class declaration can contain method defaults for methods in that class and in its (indirect) superclasses.
  2. An instance declaration can specify multiple classes
    instance (Class1 a, Class2 a, ...) where ...
    

    Subject to the constraint that:

    • No class appears more than once in the list.
    • The arguments to each class are the same.
    • For each pair of classes, Class1 and Class2 in the list:
      • Class1 is a (indirect) superclass of Class2, or
      • Class2 is a (indirect) superclass of Class1, or
      • Class1 and Class2 have a common subclass Class3 in the list.

      In other words, the superclass relation gives a connected acyclic graph with a single source, the most specific class in the heirarchy.

  3. If no implementation of a method m is given in such an instance declaration, a default is used. Multiple classes can give a default for m. If both Class1 and Class2 have a default implementation, and Class1 is a (indirect) superclass of Class2, then the default from Class1 is ignored. It is an error if more than one default remains after this process.

Class aliases

The above can be extended with class aliasses, this part of the propsal is exactly the same as John's.

  1. A class alias is declared with the syntax
    class alias Ctx => Alias a = (Class1 a, Class2 a, ..) where ...
    

    The body can contain default implementations of methods from Class1, Class2 and their superclasses.

  2. In a context, Alias a is treated the same as (Head, Class1 a, Class2 a, ..).
  3. In an instance head, Alias a is treated the same as (_Alias a, Class1 a, Class2 a, ..),
    where _Alias is considered a subclass of Class1 and Class2 that contains the default methods from the class alias body.
    class (Head, Class1 a, Class2 a, ..) => _Alias a where ...
    

    The name _Alias is a fresh name. I.e. it can not be refered to, it is used only for the purpose of this specification.