[mercury-users] errors with typeclasses

David Glen JEFFERY dgj at cs.mu.OZ.AU
Mon Oct 30 13:58:49 AEDT 2000


On 29-Oct-2000, david wallin <david at wallin.cx> wrote:
> 
> Hi all,
> 
> 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)
> 	      ].

Well, the types of add_chromosome and remove_chromosome look a bit
suspicious. Surely you can't call add_chromosome with *any* type `C'; I imagine
that there is a missing typeclass constraint. 

BTW, if I understand what get_chromosome is intended to do, I think you will
need to use an existential type. ie. 
	some [C] func get_chromosome(P, int) = C => chromosome(C)
The reason for this is that you appear to be allowing arbitrary kinds of
chromosomes to be added to the population, so when you look up a chromosome
by its index, you can't know in advance what its type will be.

Then again, perhaps you want to organise things slightly differently so that
all the chromosomes in a population are of the same type, and avoid existential
types.

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

Yes, that is a pretty weird error message. (The error message should be
improved, but to what?) The trick here is that the two `C's mentioned in the
error message are different. One is from the instance declaration, and one is
from the type of the predicate you have provided as a implementation of the
method. (Several of the errors below fall into this category).

Anyhow, the source of your problem is that the type of the typeclass method
is `pred add_chromosome(P, C, P)', which for your instance of `list(C)'
should make pred add_chromosome(list(C), C2, list(C)). (I have renamed a type
variable there to hopefully make things clearer).

However, the predicate you have provided is:
	:- pred list_add_chromosome(list(C), C, list(C)) <= chromosome(C).
	:- mode list_add_chromosome(di, in, uo) is det.

...and this type is not an instance of the expected type.

There are two errors here. First of all, your instance has an extra constraint 
that the typeclass method does not. Second, your instance requires that the
type of list elements of the first (and third) argument have to be the same
as the type of the second argument. Once again, this type is not as general
as the type class method.

The other error messages are basically repeats of these.

> 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'.
> gusga.m:085: In clause for type class method implementation:
> gusga.m:085:   unsatisfiable typeclass constraint(s):
> gusga.m:085:   `gusga: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)'.

HTH.


dgj
-- 
David Jeffery (dgj at cs.mu.oz.au) | If your thesis is utterly vacuous
PhD student,                    | Use first-order predicate calculus.
Dept. of Comp. Sci. & Soft. Eng.|     With sufficient formality
The University of Melbourne     |     The sheerist banality
Australia                       | Will be hailed by the critics: "Miraculous!"
                                |     -- Anon.
--------------------------------------------------------------------------
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