Hacker News new | ask | show | jobs
by dllthomas 4444 days ago
You can implement private mutable state (and dynamic polymorphism behind an interface) with records of closures. Depending on what you mean by "subclasses" here, they may follow trivially. Haskell typeclasses are a poor match to OOP, as you say.
1 comments

> with records of closures.

Interesting. Can you point me to an example?

http://c2.com/cgi/wiki?ClosuresAndObjectsAreEquivalent

http://okmij.org/ftp/Scheme/oop-in-fp.txt

http://stackoverflow.com/questions/2954642/methods-and-prope...

http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html

Some examples. The first is a discussion on it. The second and third have examples in scheme. I'd type more but I'm on my iPad. If I get time later I'll steal time on someone's computer to type up more.

Jtsummers gave some links, but in the interest of having something here:

    data Surface = Surface -- presumably provided by drawing backend
    data Shape = Shape
        { shapeGetCenter :: (Int, Int)
        , shapeSetCenter :: Int -> Int -> Shape
        , shapeDraw :: Surface -> IO ()
        , shapeScale :: Double -> Shape
        , shapeGetAABB :: (Int, Int, Int, Int)
        , shapeShow :: String
        }

    instance Show Shape where
        show = shapeShow

    circle r x y = Shape
        { shapeGetCenter = (x, y)
        , shapeSetCenter = circle r
        , shapeDraw = undefined -- draw shape to surface
        , shapeScale = \ f -> circle (f * r) x y
        , shapeGetAABB =
            ( floor $ fromIntegral x - r/2
            , floor $ fromIntegral y - r/2
            , ceiling $ fromIntegral x + r/2
            , ceiling $ fromIntegral y + r/2
            )
        , shapeShow = unwords [ "circle", show r, show x, show y ]
        }

    box w h theta x y = Shape
        { shapeGetCenter = (x, y)
        , shapeSetCenter = box w h theta
        , shapeDraw = undefined -- draw shape to surface
        , shapeScale = \ f -> box (w * f) (h * f) theta x y
        , shapeGetAABB =
            let w' = h * abs (sin theta)
                    + w * abs (cos theta)
                h' = w * abs (sin theta)
                    + h * abs (cos theta)
             in ( floor $ fromIntegral x - w'/2
                , floor $ fromIntegral y - h'/2
                , ceiling $ fromIntegral x + w'/2
                , ceiling $ fromIntegral y + h'/2
                )
        , shapeShow = unwords [ "box", show w, show theta, show x, show y ]
        }