
Wed, 14 Feb 2001 23:27:55 -0600, Matt Harden
I also wonder: should one be allowed to create new superclasses of an existing class without updating the original class's definition?
It would not buy anything. You could not make use of the superclass in default definitions anyway (because they are already written). And what would happen to types which are instances of the subclass but not of the new superclass?
Also, should the subclass be able to create new default definitions for functions in the superclasses?
I hope the system can be designed such that it can.
such defaults would only be legal if the superclass did not define a default for the same function.
Not necessarily. For example (^) in Num (of the revised Prelude) has a default definition, but Fractional gives the opportunity to have better (^) defined in terms of other methods. When a type is an instance of Fractional, it should always have the Fractional's (^) in practice. When not, Num's (^) is always appropriate. I had many cases like this when trying to design a container class system. It's typical that a more specialized class has something generic as a superclass, and that a more generic function can easily be expressed in terms of specialized functions (but not vice versa). It follows that many kinds of types have the same written definition for a method, which cannot be put in the default definition in the class because it needs a more specialized context. It would be very convenient to be able to do that, but it cannot be very clear design. It relies on the absence of an instance, a negative constraint. Hopefully it will be OK, since it's determined once for a type - it's not a systematic way of parametrizing code over negative constrained types, which would break the principle that additional instances are harmless to old code. This design does have some problems. For example what if there are two subclasses which define the default method in an incompatible ways. We should design the system such that adding a non-conflicting instance does not break previously written code. It must be resolved once per module, probably complaining about the ambiguity (ugh!), but once the instance is generated, it's cast in stone for this type.
What do you mean by mutual definitions?
Definitions of methods in terms of each other. Suppose there is a class having only (-) and negate, with default definitions: a - b = a + negate b negate b = zero - b When we make an instance of its subclass but don't make an explicit instance of this class and don't write (-) or negate explicitly, it would be dangerous if the compiler silently included definitions generated by the above, because both are functions which always return bottoms. The best solution I can think of is to let the compiler deduce that these default definitions lead to a useless instance, and give a warning when both are instantiated from the default. It cannot be an error because there is no formal way we can distinguish bad mutual recursion from good mutual recursion. The validity of the code cannot depend on heuristics, but warnings can. There are already warnings when a method without default is not defined explicitly (although people say it should be an error; it is diagnosable). -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK