[mercury-users] Newbie questions about typeclasses

Mark Anthony BROWN dougl at cs.mu.OZ.AU
Tue Apr 24 16:55:40 AEST 2001


Critterrathman at aol.com writes:
> First, a disclaimer.  I've been toying around with polymorphism as understood 
> in an OOP sense in a number of different languages.  I realize that Mercury 
> isn't geared towards such things, but I use it as a method to learn about 
> various programming languages.  Mercury is definitely unique in what it tries 
> to do, so I've been trying off and on to learn what I can about the language.
> 
> I've been playing around with Mercury for a while, and just haven't quite got 
> a handle on the syntax of typeclasses (not to mention some of the major 
> concepts of the language).  I don't really know enuf about the language to 
> frame my questions in a coherent manner, but I figure the only way to learn 
> is to ask dumb questions.  I apologize for not making the questions a bit 
> more straightforward but hopefully the code is fairly easy to understand (at 
> least that was the intention).  :-)
> 
> The code I'm trying to construct is the toy example of shape inheritance 
> (circle extends shape, etc...).  I include what little I've been able to 
> accomplish at the end of this message (sorry for the long post).  A couple of 
> issues that I've had at this point are:
> 
> 
> 1).  For some reason, MMC complains about not being able to find shape.int3.  
> I am trying to play with a sort of limited inheritance in this situation 
> where the circleClass inherits the method signatures of the shapeClass.  If I 
> manually copy the file shape.int2 into the requested file shape.int3, 
> everything seems to work fine.  I don't know enuf about the compiler but a 
> wild guess would be that each level of inheritance that is split across 
> modules is adding one to the index of the module file.  Of course that's a 
> WAG.  Anyhow, is there a reason why MMC exhibits this behavior?

Because mmc has only generated the "interface" files, not the "short
interface" files.  When compiling multi-module programs, it can be difficult
to manually figure out which interface files need to be generated, so we
recommend you use mmake to do it automatically.  E.g.:

	mmake main_module.depend
	mmake main_module

This should ensure that mmc generates all the interface files required.

> 
>       Here's the calls to MMC for the interface generate:
> 
>             mmc --make-int shape.m
>             mmc --make-int circle.m
> 
>       Here's the error message I get when it tries to create the interface 
> for circle.m:
> 
>             --: not found
>             mercury_compile: can't open file `shape.int3'.
>             Error reading short interface files.
>             `circle.int' and `circle.int2' not written.
> 
>       If I change the calls to the following, I get no complaints:
> 
>             mmc --make-int shape.m
>             cp shape.int2 shape.int3
>             mmc --make-int circle.m
> 

That won't work in general.  You may need to do 'mmake clean' to remove
any extra files that are lying around (you'll need to do this after the
'mmake main_module.depend' line above, and before the 'mmake main_module'
line).

> 
> 2).  I'm not sure how to get the methods for the typeclass to be used.  What 
> I wanted is to just expose the record and the typeclass definitions in the 
> interface and then map the specific function to the typeclass within the 
> implementation section of the module.  This would mean that the interface 
> might expose a method called 'getRadius' while the local method can be 
> implemented locally as 'getRadius_Circle'.  If I try to access the method by 
> the name of the typeclass method, I get an error message about an unsatisfied 
> constraint.
> 
>       Here's the call in the main routine that causes the problem:
> 
>             draw_Circle(setRadius(ACircle, 30))
> 
>       Here's the error message:
> 
>             In clause for predicate `polymorph:main/2':
>               unsatisfiable typeclass constraint(s):
>               `circle:circleClass((circle:circleRecord))'.
> 
>       However, if I don't use the typeclass and directly go to the defined 
> function, it works:
> 
>             draw_Circle(setRadius_Circle(ACircle, 30))
> 
> 
> I think I'm missing something obvious about the way that typeclasses work, 
> but I thought the purpose was to map method names from local implementation 
> names into a globally recognized method name.  The mapping of the class 
> method names into the implementation names is taken care of by the instance 
> declarations.  Just wondering what I am missing here?
> 
> Along these lines, I really didn't want to put the local implementation mode 
> into the interface section.  If I could get the method names to map off of 
> the class, I'd probably be able to push the local names into the 
> implementation section.

It sounds like you want abstract typeclass instances.  In the interface
section, mention the type and instance but don't give any definition,
like so:

	:- type circleRecord.
	:- instance shapeClass(circleRecord).
	:- instance circleClass(circleRecord).

Then in the implementation section, give full definitions of the type
and instances.

> 
> 3).  Also along similar lines, I was having difficulty getting the compiler 
> to accept pred(draw/3) in the instance declaration.  The pred() compiles fine 
> in the typeclass statement but it complains if I try to map it within the 
> instance.  I see in the documentation that it is allowed to mix predicates 
> and functions within the instance declarations.  The only proviso that I see 
> is that all the example predicates take a single constraint.  In this case, 
> the pred is doing some simple io so it requires the single argument as well 
> as the two tag along arguments for input/output.  In the code that compiles 
> and runs, I just commented out the line in the instance declaration:
> 
>       Here's the line of code that causes the problem:
> 
>             :- instance shapeClass(circleRecord) where [
>                pred(draw/3) is draw_Circle,
> 
>       Here's the error message that I get:
> 
>             In instance declaration for `shape:shapeClass/1': incorrect
>               method name(s): predicate `shape:draw/3' .
> 
> Anyhow, what exactly am I doing wrong here?

I think it is because you have not given a mode for method draw/3 in the
typeclass declaration in shape.m.  You should try adding the line

	mode draw(in, di, uo) is det,

to the declaration.

Hope this helps,
Mark.

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