Haskell' - class aliases

John Meacham john at repetae.net
Fri May 2 01:54:57 EDT 2008

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

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 Meacham - ⑆repetae.net⑆john⑈

More information about the Haskell-prime mailing list