<HTML><FONT FACE=arial,helvetica><FONT SIZE=4 FAMILY="SERIF" FACE="Times New Roman" LANG="0">First, a disclaimer. I've been toying around with polymorphism as understood
<BR>in an OOP sense in a number of different languages. I realize that Mercury
<BR>isn't geared towards such things, but I use it as a method to learn about
<BR>various programming languages. Mercury is definitely unique in what it tries
<BR>to do, so I've been trying off and on to learn what I can about the language.
<BR>
<BR>I've been playing around with Mercury for a while, and just haven't quite got
<BR>a handle on the syntax of typeclasses (not to mention some of the major
<BR>concepts of the language). I don't really know enuf about the language to
<BR>frame my questions in a coherent manner, but I figure the only way to learn
<BR>is to ask dumb questions. I apologize for not making the questions a bit
<BR>more straightforward but hopefully the code is fairly easy to understand (at
<BR>least that was the intention). :-)
<BR>
<BR>The code I'm trying to construct is the toy example of shape inheritance
<BR>(circle extends shape, etc...). I include what little I've been able to
<BR>accomplish at the end of this message (sorry for the long post). A couple of
<BR>issues that I've had at this point are:
<BR>
<BR>
<BR>1). For some reason, MMC complains about not being able to find shape.int3.
<BR>I am trying to play with a sort of limited inheritance in this situation
<BR>where the circleClass inherits the method signatures of the shapeClass. If I
<BR>manually copy the file shape.int2 into the requested file shape.int3,
<BR>everything seems to work fine. I don't know enuf about the compiler but a
<BR>wild guess would be that each level of inheritance that is split across
<BR>modules is adding one to the index of the module file. Of course that's a
<BR>WAG. Anyhow, is there a reason why MMC exhibits this behavior?
<BR>
<BR> Here's the calls to MMC for the interface generate:
<BR>
<BR> mmc --make-int shape.m
<BR> mmc --make-int circle.m
<BR>
<BR> Here's the error message I get when it tries to create the interface
<BR>for circle.m:
<BR>
<BR> --: not found
<BR> mercury_compile: can't open file `shape.int3'.
<BR> Error reading short interface files.
<BR> `circle.int' and `circle.int2' not written.
<BR>
<BR> If I change the calls to the following, I get no complaints:
<BR>
<BR> mmc --make-int shape.m
<BR> cp shape.int2 shape.int3
<BR> mmc --make-int circle.m
<BR>
<BR>
<BR>2). I'm not sure how to get the methods for the typeclass to be used. What
<BR>I wanted is to just expose the record and the typeclass definitions in the
<BR>interface and then map the specific function to the typeclass within the
<BR>implementation section of the module. This would mean that the interface
<BR>might expose a method called 'getRadius' while the local method can be
<BR>implemented locally as 'getRadius_Circle'. If I try to access the method by
<BR>the name of the typeclass method, I get an error message about an unsatisfied
<BR>constraint.
<BR>
<BR> Here's the call in the main routine that causes the problem:
<BR>
<BR> draw_Circle(setRadius(ACircle, 30))
<BR>
<BR> Here's the error message:
<BR>
<BR> In clause for predicate `polymorph:main/2':
<BR> unsatisfiable typeclass constraint(s):
<BR> `circle:circleClass((circle:circleRecord))'.
<BR>
<BR> However, if I don't use the typeclass and directly go to the defined
<BR>function, it works:
<BR>
<BR> draw_Circle(setRadius_Circle(ACircle, 30))
<BR>
<BR>
<BR>I think I'm missing something obvious about the way that typeclasses work,
<BR>but I thought the purpose was to map method names from local implementation
<BR>names into a globally recognized method name. The mapping of the class
<BR>method names into the implementation names is taken care of by the instance
<BR>declarations. Just wondering what I am missing here?
<BR>
<BR>Along these lines, I really didn't want to put the local implementation mode
<BR>into the interface section. If I could get the method names to map off of
<BR>the class, I'd probably be able to push the local names into the
<BR>implementation section.
<BR>
<BR>
<BR>3). Also along similar lines, I was having difficulty getting the compiler
<BR>to accept pred(draw/3) in the instance declaration. The pred() compiles fine
<BR>in the typeclass statement but it complains if I try to map it within the
<BR>instance. I see in the documentation that it is allowed to mix predicates
<BR>and functions within the instance declarations. The only proviso that I see
<BR>is that all the example predicates take a single constraint. In this case,
<BR>the pred is doing some simple io so it requires the single argument as well
<BR>as the two tag along arguments for input/output. In the code that compiles
<BR>and runs, I just commented out the line in the instance declaration:
<BR>
<BR> Here's the line of code that causes the problem:
<BR>
<BR> :- instance shapeClass(circleRecord) where [
<BR> pred(draw/3) is draw_Circle,
<BR>
<BR> Here's the error message that I get:
<BR>
<BR> In instance declaration for `shape:shapeClass/1': incorrect
<BR> method name(s): predicate `shape:draw/3' .
<BR>
<BR>Anyhow, what exactly am I doing wrong here?
<BR>
<BR>
<BR>Thanks in advance for any help.
<BR>
<BR>Here's the code as it currently runs.
<BR>
<BR>%%%%%%%%%%%%%%%%%%%%%%%%%%%%% polymorph.m %%%%%%%%%%%%%%%%%%%%%%%%%%%
<BR>:- module polymorph.
<BR>
<BR>:- interface.
<BR>:- import_module io, int, list, shape, circle.
<BR>:- pred main(io__state, io__state).
<BR>:- mode main(di, uo) is det.
<BR>
<BR>:- implementation.
<BR>
<BR>main -->
<BR> { Scribble = [circleRecord(10, 20, 5), circleRecord(15, 25, 8)] },
<BR> { ACircle = circleRecord(0, 0, 15) },
<BR> drawLoop(Scribble),
<BR> draw_Circle(setRadius_Circle(ACircle, 30)).
<BR>
<BR>:- pred drawLoop(list(circleRecord), io__state, io__state).
<BR>:- mode drawLoop(in, di, uo) is det.
<BR>drawLoop([]) --> [].
<BR>drawLoop([Hd | Tl]) -->
<BR> draw_Circle(Hd),
<BR> draw_Circle(rMoveTo_Circle(Hd, 100, 100)),
<BR> drawLoop(Tl).
<BR>
<BR>%%%%%%%%%%%%%%%%%%%%%%%%%%%%% shape.m %%%%%%%%%%%%%%%%%%%%%%%%%%%
<BR>:- module shape.
<BR>
<BR>:- interface.
<BR>:- import_module io, int.
<BR>
<BR>% declare method interfaces for the shape superclass
<BR>:- typeclass shapeClass(This) where [
<BR> pred draw(This, io__state, io__state),
<BR> func getX(This) = int,
<BR> func getY(This) = int,
<BR> func setX(This, int) = This,
<BR> func setY(This, int) = This,
<BR> func moveTo(This, int, int) = This,
<BR> func rMoveTo(This, int, int) = This
<BR>].
<BR>
<BR>:- implementation.
<BR>
<BR>
<BR>%%%%%%%%%%%%%%%%%%%%%%%%%%%%% circle.m %%%%%%%%%%%%%%%%%%%%%%%%%%%
<BR>:- module circle.
<BR>
<BR>:- interface.
<BR>:- import_module io, int, shape.
<BR>
<BR>% declare the constructor for circle class
<BR>:- type circleRecord
<BR> ---> circleRecord(
<BR> x :: int,
<BR> y :: int,
<BR> radius :: int
<BR> ).
<BR>
<BR>% declare method interfaces for circle subclass
<BR>:- typeclass circleClass(This) <= shapeClass(This) where [
<BR> func getRadius(This) = int,
<BR> func setRadius(This, int) = circleRecord
<BR>].
<BR>
<BR>
<BR>:- pred draw_Circle(circleRecord, io__state, io__state).
<BR>:- mode draw_Circle(in, di, uo) is det.
<BR>
<BR>:- func getX_Circle(circleRecord) = int.
<BR>:- mode getX_Circle(in) = out is det.
<BR>
<BR>:- func getY_Circle(circleRecord) = int.
<BR>:- mode getY_Circle(in) = out is det.
<BR>
<BR>:- func getRadius_Circle(circleRecord) = int.
<BR>:- mode getRadius_Circle(in) = out is det.
<BR>
<BR>:- func setX_Circle(circleRecord, int) = circleRecord.
<BR>:- mode setX_Circle(in, in) = out is det.
<BR>
<BR>:- func setY_Circle(circleRecord, int) = circleRecord.
<BR>:- mode setY_Circle(in, in) = out is det.
<BR>
<BR>:- func setRadius_Circle(circleRecord, int) = circleRecord.
<BR>:- mode setRadius_Circle(in, in) = out is det.
<BR>
<BR>:- func moveTo_Circle(circleRecord, int, int) = circleRecord.
<BR>:- mode moveTo_Circle(in, in, in) = out is det.
<BR>
<BR>:- func rMoveTo_Circle(circleRecord, int, int) = circleRecord.
<BR>:- mode rMoveTo_Circle(in, in, in) = out is det.
<BR>
<BR>:- implementation.
<BR>
<BR>% map the circle methods for shape superclass
<BR>:- instance shapeClass(circleRecord) where [
<BR> % pred(draw/3) is draw_Circle,
<BR> func(getX/1) is getX_Circle,
<BR> func(getY/1) is getY_Circle,
<BR> func(setX/2) is setX_Circle,
<BR> func(setY/2) is setY_Circle,
<BR> func(moveTo/3) is moveTo_Circle,
<BR> func(rMoveTo/3) is rMoveTo_Circle
<BR>].
<BR>
<BR>% map the methods for circle subclass
<BR>:- instance circleClass(circleRecord) where [
<BR> func(getRadius/1) is getRadius_Circle,
<BR> func(setRadius/2) is setRadius_Circle
<BR>].
<BR>
<BR>% method definitions for the circle class follow
<BR>getX_Circle(This) = This^x.
<BR>getY_Circle(This) = This^y.
<BR>getRadius_Circle(This) = This^radius.
<BR>setX_Circle(circleRecord(_,Y,Radius), X) = circleRecord(X, Y, Radius).
<BR>setY_Circle(circleRecord(X,_,Radius), Y) = circleRecord(X, Y, Radius).
<BR>setRadius_Circle(circleRecord(X,Y,_), Radius) = circleRecord(X, Y, Radius).
<BR>moveTo_Circle(circleRecord(_,_,Radius), X, Y) = circleRecord(X, Y, Radius).
<BR>rMoveTo_Circle(circleRecord(X,Y,Radius), DX, DY) = circleRecord(X+DX, Y+DY,
<BR>Radius).
<BR>
<BR>draw_Circle(This) -->
<BR> io__write_string("Drawing a circle at:("),
<BR> io__write_int(getX_Circle(This)),
<BR> io__write_string(","),
<BR> io__write_int(getY_Circle(This)),
<BR> io__write_string("), radius "),
<BR> io__write_int(getRadius_Circle(This)),
<BR> io__nl.
<BR>
<BR></FONT></HTML>