On Thu, Oct 13, 2005 at 12:21:41PM +0100, Simon Peyton-Jones wrote: > | This is a proposal for a language extension which will hopefully > mitigate the > | issues holding back evolution of the standard prelude as well as > provide > | useful class abstraction capabilities in general. > > A short summary would be "type synonyms for class constraints". You'd > definitely want the syntax to look as much like a type synonym decl as > possible.
> I've considered this before, but never done anything about it because > superclasses are so close. Specifically, what is the difference between Actually I think it is pretty orthogonal to superclasses, class aliases are about composing classes, not building hierarchies. > > (i) class (C a, D a) => CD a > and > (ii) class alias CD a = (C a, D a) > > Note that (i) is Haskell 98. > > * In both cases one can write > f :: (CD a) => ... > instead of the more voluminous > f :: (C a, D a) > > * However with (i), for each type T one must write > instance C T where { ...meths for C... } > instance D T where { ...meths for D... } > instance CD T where {} > > whereas with (ii) one can write > instance CD T where { ...meths for C... > ...meths for D... } > > I believe that this latter is the sole difference. Am I right? No, there are a number of differences that allow class aliases to be used for true class abstraction rather than just a shortcut to writing instances. > If so, than rather than invent a whole new mechanism, why not simply > extend the existing superclass mechanism to allow a single instance decl > to declare instances for several classes? For example, one add to > Haskell 98 the following: > an instance declaration for a class CD with superclasses C and D > may > give the instances for its superclasses C and D this does not actually solve the problems mentioned in the proposal. in particular, (CD a) => a and (C a,D a) => a are distinct types. this means that you cannot use the aliases as abreviations or alternate names, which is a very nice side effect. with fine grained class hierarchies, type signatures get big fast. having a shorthand is very nice. but worse, it ruins the symmetry. declaring an instance for CD a will create instances for (C a,D a) but declaring instances for C a and D a will not create one for CD. A key point of my design is that you can declare instances in the new Num hierarchy, or in the haskell 98 one, and the instances will be propagated both directions. things get much more complicated when you realize that you might want more than just 2 views of the same hierarchy and there is not a clear order among them. if you constantly have to remember to declare instances for the old haskell 98 classes too then there is really no benefit. Another illustrative example is one that combines aliases with superclasses. class alias Num a = Show a => (Additive a, Multiplicative a) now, Show is a superclass, but Num is an alias for Additive and Multiplicative. if we declare something an instance of Num, we are declaring instances for precisely Additive and Multiplicative. but not Show, there must already be an existing instance for Show since it is a superclass and not part of the alias, if this distinction were not made then several bad things happen: it is obvious you cannot emulate the old haskell 98 behavior and thus cannot get true abstraction. declaring an instance for Num where you left out 'show' would rather than give an error as it should, use the default method for show (which is undefined). this is definitly what you don't want for Show, but it might be what you want for an alternate class with a useful default. with the superclass method you mentioned, how do we control exactly which classes we are creating instances for? all the way up the hierarchy back to the base? just one level? neither rules gives us what we want and if we put that explicitly in the instance declaration we ruin the whole point of class abstraction. (plus, it seems like the wrong place to put it anyway). An instance for a class alias always and exactly declares instances for each of its components and nothing else and is orthogonal to the superclass hierarchy. Another key way in which it is different is that it is truely a composition of classes rather than a ordering on them. with a superclass relationship, classes are forced to build on top of one another, you cannot have mutual recursion between class default methods.. for instance, consider this useful little alias: class alias EqOrd a = (Eq a, Ord a) where a == b = compare a b == EQ now you can declare something as an EqOrd and just provide a 'compare' method and it will derive everything else including the Eq methods. notice that the default method is declared the wrong way in the class hierachy. this is a very handy thing, but is actually necessary to create the abstraction benefits we want. if we look at the Num example from my previous proposal: > class (Addititive a, AdditiveNegation a, > Multiplicative a, FromInteger a) => Num a where > one = fromInteger 1 > zero = fromInteger 0 > negate x = zero - x notice that one and zero are given definitons in terms of fromInteger, if these defaulting methods could not be done, then a standard haskell 98 instance for Num could not create proper instances for Additive and Multiplicative. we would basically be forced to only extend the class hierarchy by creating subsets of the current hierarchy, we could not add functions at the 'base' and expect them to get defined properly. Also, it should be noted that while I am using the Num hierarchy as an example, I think this is much more generally useful than just rewriting the prelude. the Lattice example I gave is right out of my toolbox and my anoyances with it are part of what motivated me to write this. > Anyway, my main point it: would a smaller change not suffice? I do not think it suffices. We could extend the supertyping relationship some more to make it suitable, but I think we will end up with the exact same proposal but with different terminology :) John -- John Meacham - ⑆repetae.net⑆john⑈ _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell