Haskell' - class aliases
Simon Peyton-Jones
simonpj at microsoft.com
Fri May 2 05:00:32 EDT 2008
John
This is good stuff, but I fear that in 3 months time it'll be buried in our email archives. In contrast, your original web page is alive and well, and we were able to start our discussion based on it
So can I suggest that you transfer your web page to the Haskell' wiki (simply a convenient, editable place to develop it), or to the haskell.org wiki (likewise). And that, as the design gets fleshed out, you try to reflect the current state of play there? I don't want this work to be lost!
Ok, on to your email:
=============== Desugaring the class alias decl =================
| 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)
Notice that this part *is* exactly true of a superclass with no methods
class (S a, C1 a, C2 a) => A a where {}
That's not necessarily bad; but it does make it harder to figure out when to user a superclass and when to use a class alias. Does that make sense?
In fact, I suggest the following (**): the class alias
> class alias S a => A a = (C1 a, C2 a) where
> f1 = nd1
desugars to
class (S a, C1 a, C2 a) => A a
The class alias decl *also* affects the desugaring of instances, still to come, but by desugaring the class alias into an ordinary class, you don't have to say *anything* about
g :: (S a, C1 a, C2 a) => a -> b
vs g :: (A a) => a -> b
=============== Desugaring instanc decls =================
| 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
Do you really mean that? Presumably 'a' is not a type variable here? Furthermore, instance decls typically have a context. Unless I have profoundly misunderstood, I think you mean this:
instance (Foo a, Bar b) => A (a,b) where
f1 = bf1
expands to
instance (Foo a, Bar b) => C1 (a,b) where
f1 = nd1
instance (Foo a, Bar b) => C2 (a,b) where
f2 = bf2
f2 = d3
Notice the *absence* of an instance for (S (a,b)). It's up to the *user* to ensure that there is such an instance, perhaps, say
instance Foo a => S (a,b) where ...
In this way S is behaving just like any ordinary superclass. If we have
class S a => T a
then given an instance
instance (Foo a, Bar b) => T (a,b)
it's up to the user to ensure that there is an instance for S (a,b).
With the desugaring (**) I proposed above, we'd add one more instance:
instance (Foo a, Bar b) => A (a,b)
| Hopefully the generalization to arbitrary numbers of classes is clear...
I'm not sure either way. Let's get this written up first.
Simon
More information about the Haskell-prime
mailing list