I missed out on the discussion about multiple parameter type classes
last time round, so I'm pleased to have another chance to say my piece.

I added multiple parameter classes to Gofer at a time when there
was quite a lot of discussion on this list about such classes. 

I'd been involved in these discussions and had uncovered a few
applications myself.  It wasn't at all difficult to make sure my
implementation of type classes would allow the use of multiple
parameters.  Of course, my task was a lot easier than it would have
been if I was working with a full Haskell system; I didn't have to
worry about the interaction with modules or context reduction, for
example.

Adding multiple parameter classes doesn't have any effect on the
theoretical properties of the type system:

  o  Principal types exist for all well-typed programs and can be
     calculated using the standard type inference algorithm.

  o  Coherence is guaranteed for all terms with unambiguous
     principal types.

The question of whether you are allowed to have overlapping
instance declarations is independent of whether you allow multiple
parameter classes.  The basic rule is that, if you do not do
context reduction, then you can have overlapping instance
declarations; this is the way that Gofer works.  On the other
hand, if you do context reduction, as Haskell does, then you
cannot allow overlapping instance declarations because this causes
incoherence.

With the ease of implementation, and satisfactory theoretical
properties, multiple parameter classes seemed quite promising. 

But in practice, the examples that I tried produced dissapointing
results; while there is nothing intrinsically ambiguous about
multiple parameter classes, all but one of the examples I
considered required significant use of explicit type annotations
or `asTypeOf`s to avoid ambiguities, considerably reducing their
appeal.

If a type class represents a set of types, then a multiple
parameter class corresponds to a relation between types.  My early
experiments made me think that such general relations are too weak
to be practical.  


Two relatively recent insights give cause for optimism, and
motivation for keeping multiple parameter classes in Gofer, and
for considering their introduction in Haskell:

 1) Using constructor classes, I've discovered a number of applications of
    multiple parameters where the ambiguity problems just don't seem to
    cause problems.  My paper includes one example, the StateMonad class,
    with two parameters.  I have several others, including one that uses
    four parameters with no ambiguity.

 2) In recent work, and motivated to some degree by the work on parametric
    type classes, I've been experimenting with a general system that allows us
    to impose stronger dependencies between the parameters in a class that
    avoids ambiguity in many cases.  So far, I've investigated only the
    theory side of things, for example the existence of principal
    satisfiable types.  There's a lot more work needed to fit this into a
    concrete language design.  However, I think the basic theory suggests,
    for example, that Kevin's proposal for a two parameter Num class would
    preserve the existence of principal types and the necessary coherence
    properties.

As long as we ensure that an implementation of multiple
parameters agrees with the current treatment of Haskell type
classes in the one parameter case, this extensions shouldn't cause
any problems with backwards compatibility. The real question is
whether these ideas are sufficiently mature to deserve inclusion
in the definition of Haskell, or whether we need to spend more
time playing with prototype implementations first.

All the best,
Mark

Reply via email to