[mercury-users] errors with typeclasses

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Oct 30 13:50:27 AEDT 2000


On 29-Oct-2000, david wallin <david at wallin.cx> wrote:
> 
> I've been fiddling around with typeclasses this weekend and get some 
> strange errors that I hope you can help me straighten out.
> 
> First off I have these typeclasses :
> 
> :- typeclass gene(G) where [
> 			    func mutate_gene(G) = G
> 			   ].
> 
> :- typeclass chromosome(C) where [
> 				  func mutate_chromosome(C) = C,
> 				  func gene(C, int) = G <= gene(G),
> 				  pred set_gene(C, G) <= gene(G)
> 				 ].
> 
> 
> :- typeclass population(P)
> 	where [
> 	       pred add_chromosome(P, C, P),
> 	       mode add_chromosome(in, in, out) is det,
> 
> 	       pred remove_chromosome(P, C, P),
> 	       mode remove_chromosome(in, in, out) is det,
> 
> 	       func get_chromosome(P, int) = C <= chromosome(C)
> 	      ].
> 
> 
> Basically, I want a population to be any type of structure. I then 
> tried to make a population instance :
> 
> :- instance population(list(C))
> 	where [
> 	       pred(add_chromosome/3) is list_add_chromosome,
> 	       pred(remove_chromosome/3) is list_remove_chromosome,
> 	       func(get_chromosome/2) is list_get_chromosome
> 	      ].
> 
> :- pred list_add_chromosome(list(C), C, list(C)) <= chromosome(C).
> :- mode list_add_chromosome(di, in, uo) is det.
> 
> list_add_chromosome(ListIn, Chromosome, ListOut) :-
> 	ListOut = [Chromosome | ListIn].
> 
> :- pred list_remove_chromosome(list(C), C, list(C)) <= chromosome(C).
> :- mode list_remove_chromosome(in, in, out) is det.
> 
> list_remove_chromosome(ListIn, Chromosome, ListOut) :-
> 	  list__delete_all(ListIn, Chromosome, ListOut).
> 
> :- func list_get_chromosome(list(C), int) = C <= chromosome(C).
> :- mode list_get_chromosome(in, in) = out.
> 
> 
> When I try to compile this I get the following error messages, which 
> I don't know how to interpret.
> 
> 
> gusga.m:086: In clause for type class method implementation:
> gusga.m:086:   in unification of variable `HeadVar__3'
> gusga.m:086:   and term `list_get_chromosome(HeadVar__1, HeadVar__2)':
> gusga.m:086:   type error in argument(s) of functor `list_get_chromosome/2'.
> gusga.m:086:   Argument 1 (HeadVar__1) has type `(list:list(C))',
> gusga.m:086:   expected type was `(list:list(C))'.

Unfortunately the compiler's error messages are currently not very
good in this situation.  The different occurrences of `C' in these
error messages will be referring to different type variables.  One
thing that you can do to help debug these kinds of type errors is to
use different names for type variables in different type declarations,
rather than using `C' throughout.

But the problem here is essentially that the interface of the
predicates named in the instance declaration for polulation(list(C))
doesn't match the interface specified in the population/1 type class
declaration.

In particular, the type class declaration for `get_chromosome' is

	:- typeclass population(P) where [
		...
 	        func get_chromosome(P, int) = C <= chromosome(C)
	].

i.e.

 	        all [C] func get_chromosome(P, int) = C <= chromosome(C)
		^^^^^^^

which means that the type of the return value C is independent of
the type P; for any given type P that is an instance of population/1,
the get_chromosome function must work for all types C that are are an
instance of chromosome/1.  But the function that you've specified for
this instance, namely `list_get_chromosome', has the interface

	:- func list_get_chromosome(list(C), int) = C <= chromosome(C).

which constrains the type of the return value to be the same as the
list element type.

To express relationships like this using the type class system, you
may need to use multi-parameter type classes and/or constructor classes.
Currently Mercury doesn't support constructor classes.

> gusga.m:085: In clause for type class method implementation:
> gusga.m:085:   in argument 2 of call to predicate `list_remove_chromosome/3':
> gusga.m:085:   type error: variable `HeadVar__2' has type `C',
> gusga.m:085:   expected type was `C'.

The problem reported here is the same as the one above, but for
the `remove_chromosome' method rather than `get_chromosome'.

> gusga.m:085: In clause for type class method implementation:
> gusga.m:085:   unsatisfiable typeclass constraint(s):
> gusga.m:085:   `gusga:chromosome(C)'.

This is because the type class declaration leaves `C' unconstrained,

 	       pred add_chromosome(P, C, P),
 	       mode add_chromosome(in, in, out) is det,
 
but the declaration for the predicate named in the instance declaration
adds a type class constraint on C:

	:- pred list_add_chromosome(list(C), C, list(C)) <= chromosome(C).

> gusga.m:084: In clause for type class method implementation:
> gusga.m:084:   in argument 2 of call to predicate `list_add_chromosome/3':
> gusga.m:084:   type error: variable `HeadVar__2' has type `C',
> gusga.m:084:   expected type was `C'.
> gusga.m:084: In clause for type class method implementation:
> gusga.m:084:   unsatisfiable typeclass constraint(s):
> gusga.m:084:   `gusga:chromosome(C)'.

These two are the same as for `remove_chromosome'.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list