
Axel Simon wrote:
IMHO the classes should just reflect the object hierarchy. If we have e.g.
class Button b where... class ToggleButton b where... instance Button ToggleButton where...
then we can have the simple function
onActivate :: Button b => b -> IO () -> IO ()
and use it with ToggleButton as well (but not with a plain Widget or anything on the other branches of the tree). Having onActivate as a class member doesn't give any improvement in type safety, is less efficient (bigger dictionaries) and doesn't lend itself to automatic creation of this type hierarchy.
Axel.
I'm no longer entirely sure what we are talking about. What is "the object hierarchy"? Could somebody who has an opinion on these issues knock up a concrete example; I'm not thinking of code, just some class declarations and signatures... Here's a summary of what's in the FLTK-based example that David Sankel posted a while ago. I've added some comments. class IsWidget a where toWidget :: a -> IO Widget data Widget instance IsWidget Widget class HasOnActivate a where doOnActivate :: a -> IO () -> IO( IO() ) class HasTitle w where title :: Attr w String -- This should be left to layout management: class HasPosition w where position :: Attr w (Int,Int) class HasSize w where size :: Attr w (Int,Int) -- The following two are not possible, because of some toolkits' inability to reparent widgets after creation: class HasAddChild a where addChild :: IsWidget b => a -> b -> IO () class HasChildren w ehere children :: Attr w [Widget] -- === data Window mkWindow :: [Prop Window] -> IO Window instance IsWidget window instance HasAddChild window instance HasChildren window visible :: Attr Window Bool -- === data Button mkButton :: [Prop Button] -> IO Button instance IsWidget Button instance HasTitle Button instance HasOnActivate Button instance HasPosition Button instance HasSize Button -- === -- The whole "Box" widget should probably be replaced by different kinds of boxes -- that do different kinds of layout. data Box mkBox :: [Prop Box] -> IO Box instance IsWidget Box instance HasTitle Box -- <= it seems that in fltk, a box is more than just a simple container.... instance HasPosition Box instance HasSize Box -- === Some more notes: If we want to implement a dynamic layout manager in Haskell for platforms that don't support that natively, we will need a way to query things like minimum size when we have just values of some general type (like Widget, though I already suggesting having a generic type that only includes all widgets _except_ windows). The current "CGA example" doesn't provide that. Also, the CGA example currently has completely separate code for the "HasSize" instances for Buttons and Boxes; but in the end, they both call the same virtual member function on a C++ object. There should be a way for backend implementors to avoid that needless duplication of work. Cheers, Wolfgang