Re: instance export decls

2008-05-02 Thread John Meacham
On Thu, May 01, 2008 at 03:21:11PM +0100, Simon Peyton-Jones wrote:
> Indeed! I think it'd be good to allow type signatures, including
> instance signatures, in export lists

The problem with instance signatures is that it would give the
impression that it would be possible to _not_ export an instance, and it
wouldn't make explicit the fact that the instances of all modules it
depends on are also exported. 

John

-- 
John Meacham - ⑆repetae.net⑆john⑈
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Haskell' - class aliases

2008-05-02 Thread Tom Schrijvers

class alias Foo a => Foo a = Bar a where ...


Has a defined (if not very useful) meaning with class aliases, but is
really odd if you consider 'Foo a' a "superclass". So, I think the
following terminology should be used:

  Context of --+
  alias| The alias -++--- The expansion of the alias
   |||
   vvv

class alias (S1 a .. Sn a) => A a = (C1 a ... Cn a) where
 fd1 = 
 
 fdn = 

   ^
   +  The defaults of the alias


Should all of the arguments of the Ci be the same type variable `a' as in 
the alias A a or can they be other types as well, like e.g. C1 [a] or C2 
Int?


Tom

--
Tom Schrijvers

Department of Computer Science
K.U. Leuven
Celestijnenlaan 200A
B-3001 Heverlee
Belgium

tel: +32 16 327544
e-mail: [EMAIL PROTECTED]
url: http://www.cs.kuleuven.be/~toms/
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Haskell' - class aliases

2008-05-02 Thread Claus Reinke

   A aliasing of constraints/classes
   (this is the semantic part that could also be explained by
   reduction, or by simple mutual implication encodings)

   B aliasing of syntax, especially instance definitions
   (this syntactic part is hard to encode, and simple in
   terms of syntactic macro expansion)


it just occurred to me that there is a precedence for this kind
of translation, in associated types and type functions.

defining an AT in a class is equivalent to defining a TF
outside the class, and connecting the TF to the class with
superclass and instance constraints, right?

   class C a where
   type CT a
   c :: (a,CT a)

   instance C a where
   type CT a = ..
   c = ..

   -- vs

   type family CT a
   type instance CT a = ..

   class CT a ~ b => C a where c :: (a,CT a)
   instance CT a ~ b => C a where c = ..

though the latter form is not yet supported in GHC (#714).

which leads me to a problem i have with ATs, which applies
to class aliases as well: although the ATs are written as if they
were local to the class, they get lifted out of the class in a naive
manner. in particular, they can only refer to their parameters, 
not to other local definitions/types, and their parameters have 
to match the class parameters.


however, i assume that the restrictions/translations/implementations
for class aliases are similar to the those for the implementation 
of ATs in terms of TFs, which might help?


claus



___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Haskell' - class aliases

2008-05-02 Thread Claus Reinke

hmm, i thought i understood what class aliases were about,
but the recent discussion about superclasses and fixpoints
has me confused again.

may i suggest that the updated proposal page follows this
outline (in particular, providing 1 and 2 before diving into 3):

   1. general idea + one simple example to confirm intuition
   (if there are obvious misinterpretations, it might be 
   useful to list and discard them here)

   2. translation scheme (formal enough to run all examples)
   3. concrete examples to highlight difficult issues and
   special cases
   4. syntactic sugar to make typical uses easier

the way i thought i understood them (and the way i encoded
them in the example i sent), class aliases consist of two parts:

   A aliasing of constraints/classes
   (this is the semantic part that could also be explained by
   reduction, or by simple mutual implication encodings)

   B aliasing of syntax, especially instance definitions
   (this syntactic part is hard to encode, and simple in
   terms of syntactic macro expansion)

so, in writing 


   class alias A x = (B x,C x)

we'd get 


   from A: the semantic equivalence of the constraints,
   which we usually encode roughly like this

   class (B x,C x) => A x
   instance (B x,C x) => A x
   
   from B: the syntactic equivalence of different ways

   of defining instances of A,B, and C, which
   is best understood by expanding all instance
   definitions for A into instance definitions of
   B and C

   defining instances of B x and C x is equivalent to
   defining an instance of A x (so defining an instance
   of A x if either B x or C x already exist leads to
   duplicate instances)

everything else is syntactic sugar, such as having methods
or constraints in A that are not present in B or C.

if this is wrong somewhere, could you please correct it?
otherwise, i'll wait for the updated proposal page to 
explain the details.


claus


___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Haskell' - class aliases

2008-05-02 Thread John Meacham
On Fri, May 02, 2008 at 11:54:13AM +0100, Simon Peyton-Jones wrote:
> Even more crumbs!  Is this fixpoint iteration (being careful to avoid
> infinite expansion) *really* essential to your proposal?  That would
> be a significant and unwelcome thing IMHO.
> 
> To be concrete, consider f :: (Foo a) => ...
> 
> In GHC, f really takes an extra dictionary argument for the class Foo.
> If aliases mean aliases in the sense of type synonyms (which I think
> you intend) you must expand Foo to find out whether f takes zero, one,
> or many dictionary arguments.  Furthermore, everyone must expand in
> precisely the same way, so that we agree on the order of these
> arguments.  That's reasonably simple if "expand" simply means
> "normalise"; but it's more complicated if there's a fixpoint algorithm
> involved.

Yeah, I do mean normalize I think. There is no run time representation
of class aliases at all so this issue doesn't arise. f will just take a
'Bar' dictionary argument. I am envisioning class alias expansion taking
place very early in the desugaring, certainly before any transformation
to ghc core and turning contexts into dictionary arguments. 

> So is this really crucial?

Probably not, minimal fixpoint calculations are just what I find the simplest
way to formally define/think about things. In this case, I am sure a
simpler straight up normalization algorithm can be used to get
equivalent results... but minimal fixpoints are so easy to implement in
haskell and formally well defined that I am not sure of the value of
specifying the extension in terms of it. It of course doesn't mean
compilers have to perform the fixpoint iteration, it is just a
declarative statement of what class aliases are equivalent to.

John
 

-- 
John Meacham - ⑆repetae.net⑆john⑈
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


RE: Haskell' - class aliases

2008-05-02 Thread Simon Peyton-Jones
| > Crumbs!  I have no idea what that means!  Did you really mean to repeat 
"Foo"?  According to your
| expansion in type signatures
| > f :: (Foo a) => ...
| > expands to
| > f :: (Foo a, Bar a) => ...
| > which presumably expands again.  I'm totally lost here
|
| Yes I did, because I wanted to make the differences between class alias
| contexts and superclasses very clear, the above context is valid, if
| vacuous. the expansion goes as follows .
| 1. Foo a --> reduce(Foo a,Bar a)
| -- Foo a expanded
...

Even more crumbs!  Is this fixpoint iteration (being careful to avoid infinite 
expansion) *really* essential to your proposal?  That would be a significant 
and unwelcome thing IMHO.

To be concrete, consider
f :: (Foo a) => ...

In GHC, f really takes an extra dictionary argument for the class Foo.  If 
aliases mean aliases in the sense of type synonyms (which I think you intend) 
you must expand Foo to find out whether f takes zero, one, or many dictionary 
arguments.  Furthermore, everyone must expand in precisely the same way, so 
that we agree on the order of these arguments.  That's reasonably simple if 
"expand" simply means "normalise"; but it's more complicated if there's a 
fixpoint algorithm involved.

So is this really crucial?

Simon
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Haskell' - class aliases

2008-05-02 Thread John Meacham
On Fri, May 02, 2008 at 11:24:11AM +0100, Simon Peyton-Jones wrote:
> | The more I think about it, I think 'superclass' is just the wrong
> | terminology for dealing with class aliases. Superclass implies a strict
> | partial order on classes, which just isn't the case for class aliases,
> | for instance
> |
> | > class alias Foo a => Foo a = Bar a where ...
> 
> Crumbs!  I have no idea what that means!  Did you really mean to repeat 
> "Foo"?  According to your expansion in type signatures
> f :: (Foo a) => ...
> expands to
> f :: (Foo a, Bar a) => ...
> which presumably expands again.  I'm totally lost here

Yes I did, because I wanted to make the differences between class alias
contexts and superclasses very clear, the above context is valid, if
vacuous. the expansion goes as follows .

1. Foo a --> reduce(Foo a,Bar a)
-- Foo a expanded
2. reduce(Foo a,Bar a) --> (Foo a,Bar a)  
-- no entailment reduction possible, reduction is unchanged from H98
3. (Foo a,Bar a) -> reduce(Foo a,Bar a,Bar a)
-- Foo a expanded
4. reduce(Foo a, Bar a, Bar a) -> (Foo a, Bar a) 
-- reductino removes duplicates

5. we notice we are the same as in step #2. fixed point reached, we stop
expansion.

6. we remove all class aliases from result:

(Foo a, Bar a) -> Bar a

7. 'Bar a' is our final result.


informal proof of termination:

each step adds a new class or class alias to the context, there are a
finite number of classes or class aliases, therefore we must eventually
reach a fixed point.

> Have a look at my last message, which gives a variant of your
> desugaring that IMHO greatly clarifies the meaning of (what I
> understand by) aliases.

I think the difference in what we mean is that I intend class aliases to
be a true bijection in all contexts (isomorphism?) between a single
alias and a set of classes. This is opposed to superclasses which are a
one directional implication.

One of my main motivations is being able to mix unchanged H98 and H'
code (with different numerical hierarchies, and both calling each other)
without modifications or prefered treatment for either. this means
instances for H' must silently and transparently create instances for
H98 classes and vice versa, moreso, type signatures should be
compatible.

As in, the H' specification should be able to make absolutely no
reference to H98 and vice versa, yet class aliases allow one to write a
compiler that seamlessly allows mixing code from the two without
compromising the design of either.

John

-- 
John Meacham - ⑆repetae.net⑆john⑈
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


RE: Haskell' - class aliases

2008-05-02 Thread Simon Peyton-Jones
| > Notice that this part *is* exactly true of a superclass with no
| > methods
| >
| > class (S a, C1 a, C2 a) => A a where {}
|
| No, this isn't true. imagine
|
| > f :: (S a, C1 a, C2 a) => a -> Int
| > f x = g x
|
| > g :: A a => a -> Int
| > g x = 
|
| If A is a class alias, then this compiles just fine, if A is a
| concrete class with superclasses, then it doesn't necessarily.

Excellent point.  I'll think about that -- meanwhile can you describe this 
difference explicitly in your writeup?

| > === 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:
|
| Yeah, a is likely not a type variable, so it will be of form 'S Foo' for
| some concrete type 'Foo'.

Can you give a more general example, like I did, in which we make an instance 
for A (a,b), where there is a type constructor (your Foo) but also type 
variables. Perhpas pairs are confusing; try

instance ... => A (Foo a b)

That's when the context matters!

| No, the 'S a' as appended to whatever instance context you provide. so
|
| >   instance (Foo a, Bar b) => A (a,b) where f1 = bf1
|
| expands to
|
| >   instance (S (a,b), Foo a, Bar b) => C1 (a,b) where f1 = nd1
| >   instance (S (a,b), Foo a, Bar b) => C2 (a,b) where f2 = bf2 f2 = d3
|
| If 'S (a,b)' is not entailed by the environment in scope then the
| declaration produces an error.

I don't understand why.  To be concrete, what goes wrong if you omit the (S 
(a,b))?

| of Num.  The 'class alias context' vs 'class alias expansion' is there
| to make that distinction clear and unambigous, the expansion is what you
| declare with an instance, the context is a prerequisite for creating an
| instance.

I'm not against making such a distinction -- I'm just trying to understand what 
the distinction is.


OK, this is progress.  Perhaps rather than responding in detail the next step 
is to write the proposal up in the light of where we've got to?

S
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


RE: Haskell' - class aliases

2008-05-02 Thread Simon Peyton-Jones
| The more I think about it, I think 'superclass' is just the wrong
| terminology for dealing with class aliases. Superclass implies a strict
| partial order on classes, which just isn't the case for class aliases,
| for instance
|
| > class alias Foo a => Foo a = Bar a where ...

Crumbs!  I have no idea what that means!  Did you really mean to repeat "Foo"?  
According to your expansion in type signatures
f :: (Foo a) => ...
expands to
f :: (Foo a, Bar a) => ...
which presumably expands again.  I'm totally lost here

Have a look at my last message, which gives a variant of your desugaring that 
IMHO greatly clarifies the meaning of (what I understand by) aliases.


Simon
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Haskell' - class aliases

2008-05-02 Thread John Meacham
On Fri, May 02, 2008 at 10:00:32AM +0100, Simon Peyton-Jones wrote:
> 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!

Yes. I will try to do that. if anyone else wants to go ahead and do it,
that would be fine too.

> 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 {}

No, this isn't true. imagine

> f :: (S a, C1 a, C2 a) => a -> Int
> f x = g x

> g :: A a => a -> Int
> g x = 

If A is a class alias, then this compiles just fine, if A is a
concrete class with superclasses, then it doesn't necessarily.

> 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



But there is a difference, as noted above. And how can you decide
whether the expansion:

> class S a
> class S a => A a
> instance A Int

is supposed to declare an instance for 'S Int' as well as 'A Int' or
produce an error? Neither is a good choice universally. which is why I
made the distinction explicit in my class alias proposal.

> === 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:

Yeah, a is likely not a type variable, so it will be of form 'S Foo' for
some concrete type 'Foo'. Which is checked at compile time (just as if a
method of S were used in a default) and produce an error if such an
instance doesn't exist.

>   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 ...

No, the 'S a' as appended to whatever instance context you provide. so

>   instance (Foo a, Bar b) => A (a,b) where f1 = bf1

expands to

>   instance (S (a,b), Foo a, Bar b) => C1 (a,b) where f1 = nd1
>   instance (S (a,b), Foo a, Bar b) => C2 (a,b) where f2 = bf2 f2 = d3

If 'S (a,b)' is not entailed by the environment in scope then the
declaration produces an error.

> 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)

Yes, but we explicitly did not want to add that instance by using a
class alias context rather than putting it in the expansion, for a
similar reason we don't create a dummy 'Eq' instance when someone
declares something an instance of 'Num' even though Eq is a superclass
of Num.  The 'class alias context' vs 'class alias expansion' is there
to make that distinction clear and unambigous, the expansion is what you
declare with an instance, the context is a prerequisite for creating an
instance.

John

-- 
John Meacham - ⑆repetae.net⑆john⑈
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mai

Re: Haskell' - class aliases

2008-05-02 Thread Martin Sulzmann


Any chance to express this in terms of a formal (constraint rewrite 
framework).
For example, the Haskell rule,  do *not* display implied superclasses,  
can be

specified as follows. Consider the special case of

class Eq a
class Eq a => Ord a

Eq a, Ord a <=> Ord a

The above rule only applies *after* type inference took place.

Martin



John Meacham wrote:

This isn't really a response to your email, but I have been mulling the
last few hours away from a computer and wanted to get this stream of
conciousness out when it is fresh in my mind.

The more I think about it, I think 'superclass' is just the wrong
terminology for dealing with class aliases. Superclass implies a strict
partial order on classes, which just isn't the case for class aliases,
for instance

  

class alias Foo a => Foo a = Bar a where ...



Has a defined (if not very useful) meaning with class aliases, but is
really odd if you consider 'Foo a' a "superclass". So, I think the
following terminology should be used:

   Context of --+
   alias| The alias -++--- The expansion of the alias
|||
vvv
  

class alias (S1 a .. Sn a) => A a = (C1 a ... Cn a) where
 fd1 = 
 
 fdn = 


^
+  The defaults of the alias



given this, the expansion of 'A a' in any context other than an instance
head is

  

A a --> reduce(S1 a .. Sn a, C1 a ... Cn a)



where reduce is standard entailment reduction on class contexts (like (Eq
a,Ord a, Eq a) reduces to (Ord a))

This expansion is carried out iteratively on all class aliases  until a
fixed point is reached, then all class aliases are deleted from the
result and the remaining context is the final result. (This will always
terminate due to there being a finite number of class aliases that can
be pulled into the expansion)


likewise, for instance declarations:


  

instance A a where ...



--> 

  

foreach C in C1 .. Cn:
   instance (S1 a ... Sn a) => C a where ...



I left out the default methods here. I need to think about them a bit
more to come up with a formal expansion as it is a bit trickier (to
typeset if nothing else), but I hope this is somewhat more clear for
some...

John




  


___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Haskell' - class aliases

2008-05-02 Thread John Meacham
This isn't really a response to your email, but I have been mulling the
last few hours away from a computer and wanted to get this stream of
conciousness out when it is fresh in my mind.

The more I think about it, I think 'superclass' is just the wrong
terminology for dealing with class aliases. Superclass implies a strict
partial order on classes, which just isn't the case for class aliases,
for instance

> class alias Foo a => Foo a = Bar a where ...

Has a defined (if not very useful) meaning with class aliases, but is
really odd if you consider 'Foo a' a "superclass". So, I think the
following terminology should be used:

   Context of --+
   alias| The alias -++--- The expansion of the alias
|||
vvv
> class alias (S1 a .. Sn a) => A a = (C1 a ... Cn a) where
>  fd1 = 
>  
>  fdn = 
^
+  The defaults of the alias



given this, the expansion of 'A a' in any context other than an instance
head is

> A a --> reduce(S1 a .. Sn a, C1 a ... Cn a)

where reduce is standard entailment reduction on class contexts (like (Eq
a,Ord a, Eq a) reduces to (Ord a))

This expansion is carried out iteratively on all class aliases  until a
fixed point is reached, then all class aliases are deleted from the
result and the remaining context is the final result. (This will always
terminate due to there being a finite number of class aliases that can
be pulled into the expansion)


likewise, for instance declarations:


> instance A a where ...

--> 

> foreach C in C1 .. Cn:
>instance (S1 a ... Sn a) => C a where ...

I left out the default methods here. I need to think about them a bit
more to come up with a formal expansion as it is a bit trickier (to
typeset if nothing else), but I hope this is somewhat more clear for
some...

John




-- 
John Meacham - ⑆repetae.net⑆john⑈
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Re: Haskell' - class aliases

2008-05-02 Thread John Meacham
On Fri, May 02, 2008 at 08:30:59AM +0200, Tom Schrijvers wrote:
>> 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...
>
> What about multiple parameters? Can A have more parameters than the Ci? 
> Should they be in the same order? Should they overlap?
>
> What about instance contexts, like:
>
>   instance I a => A a where ...

Ah, I originally had instance contexts in my example, but left them out
for clarity of the main points. instance contexts are just copied
verbatim into each expanded instance.

> (What about functional dependencies?)

I am leaving out MPTCs and hence fundeps for now, I do not believe they
will present an issue, as nothing about the expansion depends on the
number of arguments, but I want to make sure we have a clear
understanding of what class aliases imply for haskell 98 one constructor
type classes first. 

I think the extension to MPTCs is clear, not so clear for fundeps but
not unsolvable, then again, nothing much is clear about the future of
fundeps so I don't think that is a big issue.

John



-- 
John Meacham - ⑆repetae.net⑆john⑈
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


RE: Haskell' - class aliases

2008-05-02 Thread Simon Peyton-Jones
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

___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime