
On Mon, Oct 13, 2008 at 11:18 AM, Arun Suresh
data Point = Pt { x :: Float, y :: Float } deriving Show data Drawable = Rectangle Point Point | Circle Point Float
render :: Drawable -> IO () render (Rectangle p1 p2) = putStrLn (concat ["Rectangle from ", show p1, " to ", show p2, "."]) render (Circle center radius) = putStrLn (concat ["Circle at ", show center, " with radius ", show radius, "."])
This inverts the control from the OO structure; in the OO the interface is centralized and the data is spread throughout the source. In the pattern-matching style, the data is centralized (in the ADT) but the interface can be spread out. For example, to add a new function "area()" to Drawable, in the OO style you have to add it to Drawable and put an implementation into every class that descends from Drawable, modifying all those modules. But in Haskell you could declare a new function in one place:
area :: Drawable -> Float area (Rectangle p1 p2) = abs (x p2 - x p1) * abs (y p2 - y p1) area (Circle _ r) = pi * r * r
On the other hand, adding new data to Rectangle or Circle requires changing all the pattern matches spread throughout the source, which is somewhat annoying. So there are benefits of both styles. It's possible to emulate the OO style in Haskell, using existential types, but it is a lot harder. It's easier to stick with what the language is good at! :) -- ryan