OOP

jan@chipnet.cz jan@chipnet.cz
Mon, 10 Nov 1997 14:14:50 +0100


Nick Kallen wrote:
> 
> To some extent, I would like to remove former comments from the list. I
> realize now, that with type classes and dynamic types, the effect of type
> extensibility that I desire can be accomplished.
>     My former problem is that I thought too much in terms of extensibility
> as through -records- and not enough in terms of constructs that Clean
> already implements. Let me explain by example.
> 
> class Drawable a
> where
>     draw :: a Picture -> Picture
> 
> instance Drawable Circle
> where
>     draw circle picture = DrawCircle circle.position circle.radius picture
> 
> DrawAll :: [Dynamic] Picture -> Picture | Drawable Dynamic
> DrawAll [d:ds] pic = draw d (DrawAll ds pic)
> DrawAll [] pic = pic
> 
> Thus you can see my whole request for extensible records was pretty narrow
> minded, considering that what I want can be done without it. 

The question is not what may be done, but how much work does it take.
The draw method is not a very good example cause it probably changes in
each
and every object, but lets consider some other methods, such that use to
be 
INHERITED. Say "move". Sure we may use

:: Point = {x :: Real, y :: Real}
:: Circle = {x :: Real, y :: Real, r :: Real}

class Moveable a
 where
  move :: (Real,Real) a -> a

instance Moveable Point
 where
  move (dx,dy) point = { point & x = dx + point.x, y = dy + point.y }
 
instance Moveable Circle
 where
  move (dx,dy) circle = { circle & x = dx + circle.x, y = dy + circle.y
}

but you see that the second definition of "move" looks just like the
first
modulo the name of the type and the variable. 
Seems silly to me, consider some more complex function.
The problem is not how to make sure the right function is called,
but to reuse the functions so that I do not have to rewrite tham 
again and again even if they still look exactly the same.

I still think extensible records ARE usefull. 

BTW, I was thinking about simulating extensible records by type clases
as

:: Point = {x :: Real, y :: Real}
:: Circle = {x :: Real, y :: Real, r :: Real}

Class PointClass a
 where
  get_x :: a -> Real
  set_x :: Real a -> a
  get_y :: a -> Real
  set_y :: Real a -> a

Class CircleClass a | PointClass
 where
  get_r :: a -> Real
  set_r :: Real a -> a

instance PointClass Point
 where
  ...
 
Then if we use get_fieldname/set_fieldname instead of
record.fieldname/record&fieldname=
may define functions working on Point and all it's "ancessors".

The problem is that in the current state of clean's type system we are
unable
to overload the definition. I mean, if we define 

move :: (Real,Real) a -> a | PointClass a

we (AFAIK) may not define other

move :: (Real,Real) a -> a | SquareClass a

regardless of whether "Square | PointClass" or not. :-(


Jenda

P.S.: Take my posts easy, I have no background in type theory or
whatever.
      I'm just throwing on you my silly thoughts.