On Thu, May 01, 2008 at 11:57:14PM +0100, Simon Peyton-Jones wrote: > | > Fair enough. But the strange syntax > | > > | > class alias Num a = Eq a => (Additive a, Multiplicative a) > | > > | > *does* seem so say that the (Eq a) behaves in a superclass way, and > | > (Additive a, Multiplicative a) behave in a class-alias way, as it > | > were. That seems inconsistent with the design goal you describe > | > above. > | > | Wolfgang suggested the alternate syntax > | > | class alias Eq a => Num a = (Additive a, Multiplicative a) where .... > | > | The correct reading being: > | > | if 'Eq a' then 'Num a' is an alias for (Additive a,Multiplicative a) > | > | I think I am coming around to his point of view, do you think this makes > | it clearer? > > I am not arguing about syntax!
oh, I just meant that this syntax is actually a different way of thinking about it for me and it helped me clarify some stuff in my mind so thought it might be clearer for others as well. > > You say "class aliases are orthogonal to superclasses", but then you > allow this "Eq a" thing in the above alias, which is very like a > superclass. I think that if you allow the "Eq a =>" part, you should > also allow new methods to be declared in the alias (as I originally > thought you did). And if not, then you shouldn't allow superclasses. > It's precisely that you allow superclasses (Eq a =>) that makes your > feature non-orthogonal to ordinary superclasses. Maybe you can't make > them orthogonal, but it quite hard to explain this definition to me. Oh, the reason to allow superclasses of class aliases is so methods of the superclass can be used in the default instance methods for your alias. In addition, it allows full emulation of any explicit class you can currently declare. You do not want 'instance 'Num a'' to declare an instance for Eq as that is very different behavior from the old Num class. Yet the default instances for 'Num' may require use of methods from its superclass. it actually would make more sense to call them the context of the class alias rather than the superclass, since they don't declare a super/sub class relationship between the two. > Incidentally, you say that your proposal is just syntactic sugar: if > so, can you give the desugaring translation? Hmm.. okay, here is a rough draft that covers all the important cases I think. assume the following declarations: > class C1 a where > f1 :: t1 > f1 = d1 > class C2 a where > f2 :: t2 > f2 = d2 > f3 :: t3 > f3 = d3 > class alias S a => A a = (C1 a, C2 a) where > f1 = nd1 okay, the desugaring is as follows: there are two different desugaring rules, one for instances, one for the alias appearing anywhere other than an instance declaration: > g :: A a => a -> b > g = ... translates to > g :: (S a, C1 a, C2 a) => a -> b > g = ... the triplet of (S a, C1 a, C2 a) is completely equivalent to (A a) in all ways and all places (other than instance heads), one is just a different way to express the other, just like type synonyms. An alias just expands to the union of the classes it is an alias for as well as its class constraints (superclasses). now for instance declarations > instance A a where > f2 = bf2 expands to > instance (S a) => C1 a where > f1 = nd1 > instance (S a) => C2 a where > f2 = bf2 > f3 = d3 Note that when declaring an instance of a concrete type, like Int, the constraint (S Int) will be trivially satisfied or not at compile time. (bf2 is free to use methods of 'S' of course). this translation is also a bijection, declaring those two instances manually as above is indistinguishable from declaring instances via the alias in all ways. Hopefully the generalization to arbitrary numbers of classes is clear... John -- John Meacham - ⑆repetae.net⑆john⑈ _______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime