Re: Haskell' - class aliases

2008-05-06 Thread Claus Reinke

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

I'm not sure what you mean here, Claus.  Can you give a concrete example?


sure. here's one from practice, even. there was a thread on haskell-cafe
on how to re-export FD-based libraries in AT-based form (for better
match with AT-based client code). the obvious translation of

   class FD a b | a - b

would seem to be

   class AT a where type AT a

but, as it turns out, you can't write

   instance FD a b = AT a where type AT a = b

because the 'b' is not in scope! from an AT-based perspective,
it ought to be in scope, because the AT definition is local to the 
instance, but the AT seems to be implemented as sugar for a

non-local TF, for which the local 'b' is not available (i'm not sure
why there is no lambda-lifting behind the scenes to add that 'b'
parameter, in a hidden form?).

the thread, and Manuel's explanation, are here:

http://www.haskell.org/pipermail/haskell-cafe/2008-March/041168.html

this is likely to be less of a problem for class aliases, because
the component class instances share not only the same form 
of instance head, but also the same context (so if a type is 
functionally determined by the context in one component, it

is so in all components).

btw, if type family instances could have contexts that functionally 
determine extra type parameters, the original poster wouldn't have 
to duplicate his FDs as TFs, as suggested in that email, but could 
simply write (i think?-):


   type instance AT a = FD a b = b

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 Tom Schrijvers

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


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

(What about functional dependencies?)

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 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
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/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 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 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 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-01 Thread John Meacham
On Thu, May 01, 2008 at 03:42:53PM +0100, Simon Peyton-Jones wrote:
 | Yeah, I disagree here, mainly because I don't want to conflate
 | superclasses with class aliases. I feel they have different uses, even
 | though they can sometimes achieve the same thing.
 
 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?

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-01 Thread Simon Peyton-Jones
|  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!

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.

Incidentally, you say that your proposal is just syntactic sugar: if so, can 
you give the desugaring translation?

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


Re: Haskell' - class aliases

2008-05-01 Thread John Meacham
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


Re: Haskell' - class aliases

2008-04-25 Thread Claus Reinke

Is this the most up-to-date description of the proposal?
http://repetae.net/recent/out/classalias.html


what sounds nice about the class alias proposal is that it is pure
sugar, at least to the extent that type aliases are, but the design 
principle behind it seems to be that there should be a separate 
class for each method (as in Clean?), and that any compound 
classes should really just be class aliases (made to look like 
compound classes by the sugar), so that rearranging compound
classes comes down to defining more aliases for the same 
single-method base classes.


since this looks like class equivalence plus namespace handling,
i was wondering how far one could get without the proposed 
extension. this is slightly more difficult than the proposed translation

(which splits compound aliases into their components, so that the
alias class is always translated away), but it might still be of interest.

consider the 'class alias FooBar a = (Foo a,Bar a)' example
from the proposal page. we define FooBar and Foor/Bar in
separate modules and use that for namespace management.

- FooAndBar defines Foo and Bar, as well as a type X
   which is an instance of both

- FooBar defines FooBar, implicit derivations of FooBar 
   from Foo/Bar and vice-versa (the aliasing part), as well 
   as a type Y which is an instance of FooBar


   FooBar also arranges for Y to be an instance of Foo/Bar,
   and for X to be an instance of FooBar, via the implicit
   derivations, but controlled by instances of How

note the class 'How' and its instances, which ensure that 
any type class instance is either defined, or derived (in

a unique, specified way), but never both.

problems:

(1) instance method definitions by qualified names are
   not permitted, leading to the confusing 'foo = foo'
   (cf separate thread)
   
(2) overlapping instances, due to the derived instances;
   it seems this can be held in check by the use of 'How', 
   at the expense of some extra parameters/contexts/

   instances to control how each instance is defined/derived

example session:

   *FooBar foo (X 1)
   False
   *FooBar bar 0 (X 1)
   [X 1]
   *FooBar foo (Y 1)
   True
   *FooBar bar 0 (Y 1)
   [Y 1,Y 1]

   *FooBar FooAndBar.foo (X 1)
   False
   *FooBar FooAndBar.foo (Y 1)
   True
   *FooBar FooAndBar.bar 0 (X 1)
   [X 1]
   *FooBar FooAndBar.bar 0 (Y 1)
   [Y 1,Y 1]

   *FooBar :t foo
   foo :: (FooBar a how) = a - Bool
   *FooBar :t FooAndBar.foo
   FooAndBar.foo :: (Foo a how) = a - Bool
   *FooBar :t bar
   bar :: (FooBar a how) = Int - a - [a]
   *FooBar :t FooAndBar.bar
   FooAndBar.bar :: (Bar b how) = Int - b - [b]

i don't think i'd recommend this encoding style (it does not
quite fullfill the criterion of simplicity!-), but there you are:
class aliases encoded.

hth,
claus

ps. (for the TF vs FD fans: replacing FD class 'How' 
   with a TF doesn't seem to work; a bug?)




FooAndBar.hs
Description: Binary data


FooBar.hs
Description: Binary data
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


RE: Haskell' - class aliases

2008-04-25 Thread Simon Peyton-Jones
John

OK here's a question about class alisas. You propose:

   class Foo a where
foo :: a - [a]
foo x = []
   class Bar a where
bar :: a - a
bar x = [x]

   class alias FooBar a = (Foo a, Bar a) where
foobar :: a - a
foobar x = x

foo x = bar x

I have a few minor questions about this that'd be worth clarifying on your main 
page
  (a) I assume you can add a method 'foobar' not declared
in either Foo or Bar.  Your very first example has this.
But it's contradicted later when you say that One can declare an 
instance
of Num either by giving separate instances for Eq, Additive, 
Multiplicative

  (b) And I assume that you don't need to repeat the type
signatures for 'foo' and 'bar'.

  (c) I think you intend that you can override the default methods
for foo and bar; and I have done so for method 'foo'.

Question: how does the above differ from this?

   class (Foo a, Bar a) = FooBarSC a where
foobar :: a - a

Here Foo, Bar are simply superclasses.  From the point of view of a type 
signature there *no* difference:

f :: (FooBarSC a) = ...

gives access to all the methods of Foo and Bar.  So what's the difference?

Answer (I believe): when you give an instance of FooBar
you give implementations for all methods of
Foo, Bar, and FooBar.

So the obvious question is: do we really need a new construct?  Why not just 
use FooBarSC?  Then we'd have to allow you to give implementations for 
superclass methods too:
instance FooBarSC Int where
  foobar = ...
  foo = ...
  bar = ...

I think I believe (like you) that this is a bad idea.  The main reason is that 
it's a totally unclear whether, given a FooBarSC Int instance declaration, 
should there be an instance for (Foo Int), always, never, or optionally?

However, I think you might want to articulate the reasons carefully, because we 
have two features that are really extremely close.

To put it another way, you could imagine re-expressing your proposal like this:

  class (Eq a)  (Additive a, Multiplicative a) = Num a

meaning this: when you give an instance for (FooBar T) you

 * MUST give implementations for the methods
of Addititive and Applicative

 * MUST NOT give implementations for methods of Eq;
rather the Eq T instance must be in scope.

This is, I believe, what you mean by
  class alias Num a = Eq a = (Additive a, Multiplicative a)

Now I'm not necessarily suggesting this as concrete syntax.  But my point is 
that you're really asking for small modification of the existing superclass 
mechanism, that divides the superclasses into two groups, the flat ones (like 
Additive and Multiplicative) and the nested ones (like Eq).  Is that right? 
If so, a syntax that is more suggestive of the current superclass declaration 
looks better to me.

This close relationship also suggests strongly that the answer to (a) above 
should be 'yes', since you can certainly add methods to a class with 
superclasses.


I won't say more until I'm sure I've understood your intent.

Simon



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


Re: Haskell' - class aliases

2008-04-25 Thread Twan van Laarhoven

Simon Peyton-Jones wrote:


Is this the most up-to-date description of the proposal?
http://repetae.net/recent/out/classalias.html


Has anyone looked at my (confusingly named and horribly written) variant?

  http://haskell.org/haskellwiki/Superclass_defaults


My idea is to split class aliases into two separate things:

  1. Superclass defaults: allow a class declaration to contain defaults for 
methods from superclasses. Allow an instance declaration to be for multiple 
classes at once, using the most specific defaults:


   instance (FooBar a, Foo a, Bar a)
 -- pick the defaults from FooBar, since it is a subclass
 -- of both Foo and Bar.

  2. Class aliases: simply an alias for zero or more classes.

   class alias FooAndBar a = (Foo a, Bar a)

 In a context FooAndBar a is simply replaced by (Foo a, Bar a). For 
instantiation purposes the class alias could override the default methods as if 
it was a subclass of Foo and Bar. No new methods can be added.

 Alternatively class aliases could be just macros, like type synonyms.


Part 1 applies for instance to the Functor/Applicative/Monad hierarchy, fmap 
could have a default in terms of (=).

Part 2 is useful for splitting classes up into smaller bits.


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


Re: Haskell' - class aliases

2008-04-25 Thread John Meacham
On Thu, Apr 24, 2008 at 10:21:03PM +0200, Wolfgang Jeltsch wrote:
 Am Donnerstag, 24. April 2008 21:27 schrieb John Meacham:
  On Thu, Apr 24, 2008 at 08:48:15PM +0200, Wolfgang Jeltsch wrote:
  […]
 
   I also have some remark: Why not write
  
class Eq a = Num a = (Additive a, Multiplicative a)
  
   instead of
  
class Num a = Eq a = (Additive a, Multiplicative a)
 
  Well, because you can think of 'Num a' as an alias for 'Eq a =
  (Additive a, Multiplicative a)', not that Eq is a superclass of Num
  which the class declaration syntax implies.
 
 Hmm, in what way is Num a an alias for Eq a = (Additive a, Multiplicative 
 a)?  
 You cannot write this:
 
  square :: (Eq a = (Additive a, Multiplicative a)) = a - a
 
 I would say: “Under the condition that Eq a holds, Num a is an alias for 
 (Additive a, Multiplicative a).  And this seems to be perfectly expressed by 
 my above proposal.

Hmm... I guess it depends on how you think about it. I tend to think
about them in terms of what they are rewritten to rather than a
proposition about classes. but perhaps that makes more sense. Will mull
on it 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-04-24 Thread Wolfgang Jeltsch
Am Mittwoch, 23. April 2008 06:18 schrieb John Meacham:
 On Tue, Apr 22, 2008 at 08:33:53AM +0100, Simon Peyton-Jones wrote:
  Is this the most up-to-date description of the proposal?
  http://repetae.net/recent/out/classalias.html

 There were a few changes proposed in the discussion that followed my
 announcement that I wanted to make. The one I can remember now is
 getting rid of the 'alias' keyword since the equals sign unabiguously
 identifies it as an alias. I will dig through the archive to find the
 others..

  I've just had another look, which threw up quite a few questions in my
  mind.   I wonder what would be a good list to discuss it.  Maybe this
  one is not bad, because it has people interested in Haskell
  innovation, regardless of whether it's a live Haskell' candidate?

 Sounds good to me.

 John

By the way, what are your current thoughts about your supertyping proposal.  
At least, on http://repetae.net/recent/out/supertyping.html you say:

 This functionality becomes even more necessary when faced with binary-only
 libraries and standard language features which cannot be easily rewritten or
 overridden without great effort.  

This seems to be an advantage compared to the class alias library.  On the 
other hand, it looks a bit weird to me that you can express a class relation 
in two different ways: A t = B t and B t = A t.

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


RE: Haskell' - class aliases

2008-04-22 Thread Simon Peyton-Jones
| I tried to see the discussion that led to class aliases being rejected
| as a proposal, but could not find links on the Wiki.  In fact, in Trac
| (#101) that proposal is still a 'maybe', but with no updates.  Is there
| a competing proposal that got accepted?
|
| [Without a mechanism like class aliases, breaking up Num into a
| hierarchy of proper mathematical concepts becomes too unwieldly to be
| realistic.  This is a real stumbling block for anyone trying to use the
| class system to encode fine-grained mathematical concepts.]

I think this is partly my fault for failing to implement the idea -- a full 
implementation is really a prerequisite for Haskell'.

One reason I've failed to do so is because I have not come under enough 
pressure!  If I thought there were dozens of people slavering at the chops for 
class aliases, that would put it more firmly on my radar.  Ben is right to say 
that it's much easier than the type-function stuff, which is decidedly tricky.  
 (Of course there nothing stopping someone else doing it, but GHC's typechecker 
is one of it's more richly-interconnected parts.)   Perhaps you have all just 
been very polite, and waiting in quiet but unrequited hope.

Is this the most up-to-date description of the proposal?
http://repetae.net/recent/out/classalias.html

I've just had another look, which threw up quite a few questions in my mind.   
I wonder what would be a good list to discuss it.  Maybe this one is not bad, 
because it has people interested in Haskell innovation, regardless of whether 
it's a live Haskell' candidate?

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


Re: Haskell' - class aliases

2008-04-22 Thread John Meacham
On Tue, Apr 22, 2008 at 08:33:53AM +0100, Simon Peyton-Jones wrote:
 Is this the most up-to-date description of the proposal?
 http://repetae.net/recent/out/classalias.html

There were a few changes proposed in the discussion that followed my
announcement that I wanted to make. The one I can remember now is
getting rid of the 'alias' keyword since the equals sign unabiguously
identifies it as an alias. I will dig through the archive to find the
others..

 I've just had another look, which threw up quite a few questions in my
 mind.   I wonder what would be a good list to discuss it.  Maybe this
 one is not bad, because it has people interested in Haskell
 innovation, regardless of whether it's a live Haskell' candidate?

Sounds good to me.

John

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


Haskell' - class aliases

2008-04-21 Thread Jacques Carette
I tried to see the discussion that led to class aliases being rejected 
as a proposal, but could not find links on the Wiki.  In fact, in Trac 
(#101) that proposal is still a 'maybe', but with no updates.  Is there 
a competing proposal that got accepted?


[Without a mechanism like class aliases, breaking up Num into a 
hierarchy of proper mathematical concepts becomes too unwieldly to be 
realistic.  This is a real stumbling block for anyone trying to use the 
class system to encode fine-grained mathematical concepts.]


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


Re: Haskell' - class aliases

2008-04-21 Thread Simon Marlow

Jacques Carette wrote:
I tried to see the discussion that led to class aliases being rejected 
as a proposal, but could not find links on the Wiki.  In fact, in Trac 
(#101) that proposal is still a 'maybe', but with no updates.  Is there 
a competing proposal that got accepted?


[Without a mechanism like class aliases, breaking up Num into a 
hierarchy of proper mathematical concepts becomes too unwieldly to be 
realistic.  This is a real stumbling block for anyone trying to use the 
class system to encode fine-grained mathematical concepts.]


We want to get Haskell' done, and unfortunately that may mean rejecting 
some good proposals - in this case, class aliases is a fairly large 
feature that we don't have enough experience with yet, so it was dropped 
(I proposed dropping it recently to the committee, and no-one argued 
against).


That's not to say it isn't worthwhile, and this certainly doesn't 
prevent it from being adopted in a future version of the standard.  We'd 
 like to see it implemented in GHC, too.


BTW, by the end of this process I do want to make sure we've documented 
the rationale for all the decisions, so that future committees have a 
useful knowledge base to work from.


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