The composite design pattern implemented using record types,
where the named elements are the interface to the object

Overall, I think I agree with Tim that the record types are simpler to code.

I'm not sure, though, what would happen if I tried to add state to the types. With the previous example, using existentials to create a reference type that holds elements of a type class that matches the interface, I think that it would be natural to hold state by having that element stored in a mutable state variable, and replacing the held values.

In any case:

Two methods, add and draw

> data Component = Component {
>     draw :: String,
>     add ::  Component -> Component
>     }

A constructor for the leaf type, which holds a string

> leaf :: String -> Component
> leaf s =
>     Component draw1 add1
>               where draw1 = show s
>                     add1 _ = leaf s

the draw method for the composite type
(because I was having trouble with layout and formating for 72 cols)

> compositeDraw :: [Component] -> String
> compositeDraw []  = "()"
> compositeDraw leaves  = "(" ++ (foldr1 (++) $ map draw leaves) ++ ")"


A constructor for the composite type, which holds a list of components
and dispatches to the contained elements

> composite :: [Component] -> Component
> composite cs =
>     Component draw1 add1
>               where draw1 = compositeDraw cs
>                     add1 c = composite $ c:cs



On 2/27/07, Tim Docker < twd_gg@dockerz.net> wrote:
Steve Downey wrote:
> interesting. it leads to something that feels much more like an object
based, as opposed to a class based, system.
> as far as haskell is concerned, everything has the same type, even
though different instances have very different behavior.
> ....
> the question is, which plays nicer with the rest of haskell? that is, if
i'm not committing to a closed dsl, which style is more likely to be
reusable against other libraries.

I suspect there's no right answer - it's a case of choosing the
best approach for the problem. As an example, my charting library
(http://dockerz.net/software/chart.html) uses the record of functions
approach for composing drawings:

data Renderable = Renderable {
    minsize :: (Render RectSize)
    render :: (Rect -> Render ())
}

Tim