O'Haskell

Contributed by Chris Rathman

Note: I could not figure out how to call one method from another method within the class. As a result, the accessors are not used by the methods within the class definitions.

Shape class (shape.hs)

module Shape

   where

   -- declare method interfaces for the shape superclass
   struct Shape =
      getX :: Cmd Int
      getY :: Cmd Int
      setX :: Int -> Cmd ()
      setY :: Int -> Cmd ()
      moveTo :: Int -> Int -> Cmd ()
      rMoveTo :: Int -> Int -> Cmd ()
      draw :: Cmd ()

Rectangle class (rectangle.hs)

module Rectangle

   where

   -- declare method interfaces for rectangle subclass
   struct Rectangle < Shape =
      getWidth :: Cmd Int
      getHeight :: Cmd Int
      setWidth :: Int -> Cmd ()
      setHeight :: Int -> Cmd ()

   -- declare the constructor for the rectangle class
   rectangle (env, initx, inity, initwidth, initheight) =

      -- slots for the object state variables
      template
         x := initx
         y := inity
         width := initwidth
         height := initheight

      -- define the methods for the rectangle class
      in struct

         -- accessors for x & y coordinates
         getX = request
            return x
         getY = request
            return y
         setX newx = action
            x := newx
         setY newy = action
            y := newy

         -- move the x & y coordinates
         moveTo newx newy = action
            x := newx
            y := newy
         rMoveTo deltax deltay = action
            x := x + deltax
            y := y + deltay

         -- accessors for width & height
         getWidth = request
            return width
         getHeight = request
            return height
         setWidth newwidth = action
            width := newwidth
         setHeight newheight = action
            height := newheight

         -- draw the rectangle
         draw = request
            env.putStr("Drawing a Rectangle at:(" ++ (show x) ++ "," ++ (show y) ++
               "), width " ++ (show width) ++ ", height " ++ (show height) ++ "\n")

Circle class (circle.hs)

module Circle

   where

   -- declare method interfaces for circle subclass
   struct Circle < Shape =
      getRadius :: Cmd Int
      setRadius :: Int -> Cmd ()

   -- declare the constructor for the circle class
   circle (env, initx, inity, initradius) =

      -- slots for the object state variables
      template
         x := initx
         y := inity
         radius := initradius

      -- define the methods for the circle class
      in struct

         -- accessors for x & y coordinates
         getX = request
            return x
         getY = request
            return y
         setX newx = action
            x := newx
         setY newy = action
            y := newy

         -- move the x & y coordinates
         moveTo newx newy = action
            x := newx
            y := newy
         rMoveTo deltax deltay = action
            x := x + deltax
            y := y + deltay

         -- accessors for the radius
         getRadius = request
            return radius
         setRadius newradius = action
            radius := newradius

         -- draw the circle
         draw = request
            env.putStr("Drawing a Circle at:(" ++ (show x) ++ "," ++
               (show y) ++ "), radius " ++ (show radius) ++ "\n")

Try shapes function (polymorph.hs)

module Polymorph(main)

   where
   import Shape
   import Circle
   import Rectangle

   main env =
      do
         -- create some shape instances
         s1 <- (rectangle (env, 10, 20, 5, 6))
         s2 <- (circle (env, 15, 25, 8))
         let scribble = s1:s2:[]

         -- iterate through the list and handle shapes polymorphically
         drawloop scribble

         -- call a rectangle specific function
         r <- (rectangle (env, 0, 0, 15, 15))
         r.setWidth 30
         r.draw

   drawloop [] = return ()
   drawloop (x:xs) =
      do
         x.draw
         x.rMoveTo 100 100
         x.draw
         drawloop xs

Output

Drawing a Rectangle at:(10,20), width 5, height 6
Drawing a Rectangle at:(110,120), width 5, height 6
Drawing a Circle at:(15,25), radius 8
Drawing a Circle at:(115,125), radius 8
Drawing a Rectangle at:(0,0), width 30, height 15

Chris Rathman / Chris.Rathman@tx.rr.com