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: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of [EMAIL PROTECTED] > 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 shapes; > > for(std::list::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 ___ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
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 shapes; > for(std::list::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
RE: Re[2]: [Haskell] Dynamic binding
Bulat, Bulat wrote: > just create list of draw functions itself: > > [drawCircle (10,10) 5, drawSquare (20,20) 10] No! the exercise is about lists of shapes not lists of results of drawing shapes. This is clearly a major difference. Bulat wrote: > for more complex tasks - declare interface as a structure: > > data ShapeInterface = Shape { draw :: IO (), > moveTo :: Point -> IO (), > calcArea :: Float > } No! You miss the point that the different shapes differ regarding state types. You don't have a chance when you use one datatype. haskell-cafe? Ralf > -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Bulat Ziganshin > Sent: Thursday, June 23, 2005 12:18 AM > To: Andrew Ward > Cc: Pal-Kristian Engstad; haskell@haskell.org > Subject: Re[2]: [Haskell] Dynamic binding > > Hello Andrew, > > Thursday, June 23, 2005, 5:38:03 AM, you wrote: > > AW> To handle the problem of drawing all shapes, in c++, I would have a > list > AW> of shape pointers: > > AW> struct shape{ virtual void draw(...);}; > AW> struct circle : public shape {...}; > AW> struct square : public shape {...}; > AW> std::list shapes; > AW> for(std::list::iterator it = shapes.begin();it != > AW> shapes.end();++it) > { (*it)->>draw(...); } > > AW> This general pattern of dynamic binding I use over and over again. > Could > AW> you give me some example code of this type of thing handled in > Haskell's > AW> way? Assuming that the number of classes deriving from shape might get > AW> quite large. > > just create list of draw functions itself: > > [drawCircle (10,10) 5, drawSquare (20,20) 10] > > you are not expected that this problem can be solved with one line of > code? :) > > > for more complex tasks - declare interface as a structure: > > data ShapeInterface = Shape { draw :: IO (), > moveTo :: Point -> IO (), > calcArea :: Float > } > > > and return this structures from "constructor" functions: > > circle x y r = Shape { draw = drawCircle center r, >moveTo newCenter = , >calcArea = pi*r*r > } >where center = Point x y > > square x y size = Shape { draw = , > moveTo newCenter = , > calcArea = size*szie > } > > figures = [circle 1 2 3, square 4 5 6, circle 7 8 9] > > > > of course, you cannot use inherited field names when using this > technique :) > > -- > Best regards, > Bulatmailto:[EMAIL PROTECTED] > > > > ___ > Haskell mailing list > Haskell@haskell.org > http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell