RE: Re[2]: [Haskell] Dynamic binding
Andrew, you are circumventing the hard problem! (Even though I am sure you just forgot to mention it.) That is, the question is about drawing a *list* of shapes. As correctly observed by Rathman ages back, one naturally ends up with existential quantification when simulating dynamic binding. Ex. quantification is sufficiently scary for folks moving from C++ to Haskell. But fortunately it's not necessary ... see earlier plug ... Ralf
-----Original Message----- From: haskell-bounces@haskell.org [mailto:haskell-bounces@haskell.org] On Behalf Of ajb@spamcop.net Sent: Thursday, June 23, 2005 12:42 AM To: haskell@haskell.org Subject: Re: Re[2]: [Haskell] Dynamic binding
G'day all.
Thursday, June 23, 2005, 5:38:03 AM, you wrote:
To handle the problem of drawing all shapes, in c++, I would have a list of shape pointers:
struct shape{ virtual void draw(...);}; struct circle : public shape {...}; struct square : public shape {...}; std::list<shape *> shapes; for(std::list<shape *>::iterator it = shapes.begin();it != shapes.end();++it) { (*it)->>draw(...); }
This general pattern of dynamic binding I use over and over again. Could you give me some example code of this type of thing handled in Haskell's way? Assuming that the number of classes deriving from shape might get quite large.
class Drawable s where draw :: s -> IO ()
data Circle = Circle Point Radius
instance Drawable Circle where draw (Circle centre radius) = ...
If you only need interface inheritance, this should do. If you also need implementation inheritance, then you can model it with an upcast method:
data Shape = Shape Stuff
class Shape s where toShape :: s -> Shape draw :: s -> IO ()
instance Shape Shape where toShape s = s draw s = ...
data Circle = Circle Shape Point Radius
instance Shape Circle where toShape (Circle s _ _) = s draw (Circle _ centre radius) = ...
In your original example, draw() wasn't abstract virtual, so I assume there's a reasonable default draw() method for your "shape" class. If there isn't, then it's probably better in Haskell to split the typeclass:
class Shape s where toShape :: s -> Shape
class (Shape s) => DrawableShape s where draw :: s -> IO ()
And only define DrawableShape on types where "draw" makes sense.
Cheers, Andrew Bromage _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
participants (1)
-
Ralf Lammel