
I'll try to summarize the discussion about how to arrange the class/object hierarchy, admittedly with some bias towards my own opinions. I'd just like to confirm if we really have agreed on what I think we've agreed [like many people, I have a tendency to think that everyone agrees with my opinions unless I hear a clear "no" :-) ]. So what have we already agreed on? 1) There will be a datatype Window 2) There will be a datatype Pane 3) ... along with a class IsPane (or PaneClass or ...) class IsPane p where toPane :: p -> Pane 4) There will be a class Container class Container c where -- member functions to be determined And we'll have 4a) instance Container Window 4b) instance Container GridBox Open Issue/Disadvantage of this solution: What type would a "getContainer" function have? Can we have such a function at all? What are the alternatives to a class Container? 5) For a particular widget type Foo, we will have 5a) data Foo 5b) instance IsPane Foo 5c) newFoo :: Container c => c -> [Prop Foo] -> IO Foo 6) GridBox is a layout container that works like Gtk's Table, Java's GridBagLayout and Tk's grid. It should be implemented using Gtk's Table for Gtk, and implemented in Haskell for other platforms. We have 6a) instance IsPane GridBox 6b) instance Container GridBox 6c) Layout constraints can be set using attributes: column :: IsPane p => Attr (GridBox, p) Int (and more attributes as required for a grid layout algorithm) Example: box <- newGridBox container [columns =: 2, rows =: 2] button <- newButton box [...] set (box,button) [column =: 1, row =: 1] 7) Below the "Pane" type and class, we'll try to keep the hierarchy flat (perhaps even absolutely flat), so that we don't have any problems with mismatches between the interface and backend implementations. === Undecided issues: 8) Will there be a datatype for a general Widget (in addition to the datatype for a general Pane (Point 2)) ? data Widget along with class IsWidget w where toWidget :: w -> Widget Pros: *] Common features of Windows and Panes can be implemented very conveniently on platforms where both Windows and Panes are represented by a "Widget" object. *] Having both getWindowSize and getPaneSize seems unnatural; having getSize in a type class sounds nice, but might require that all Pane types explicitly instantiate that class, always with the same implementation, for example: instance HasSize Button where getSize b = getSize (toPane b) Cons: *] Not all platforms have that common representations; implementations on other platforms would have to use a discriminated union type and lots of case expressions, for example: getSize w = case toWidget w of WindowWidget win -> getWindowSize win PaneWidget pane -> getPaneSize pane *] The only common feature of Windows and Panes that I can think of is size and position on screen. *] The Parent/Child relationship is not such a common feature, as there are no cross-platform parent/child relationships between toplevel windows. Also, one widget being contained in another widget is not the same thing as one window being a child of another window (the latter has nothing to do with containment, except with MDI). *] There's no reason to need a general list of widgets, where Panes and Windows can be freely mixed. 9) Do we prefer to use a) too many type classes, i.e. a HasFoo class even when there's only one widget that supports foo, or do we rather want to risk having b) too few type classes, i.e. making foo a plain function when we may later add another widget that supports the exact same foo? I think the performance costs of type classes are absolutely negligible, but what about namespace polution and readability of error messages? So that's all for now, feel free to add your own points. - I'd also like to know what other people think I've agreed to, when in fact I haven't :-). Cheers, Wolfgang