At 14:32 30-1-03 +0100, Daan Leijen wrote:
[..]
However, it is not yet clear how that level should look like. We could take
the ObjectIO interface as our layer but I would not recommend that.
Note, this is not a critique on the ObjectIO library, I highly respect the work
of the Clean people, and Peter van Achten in particular. However, the Haskell
ObjectIO interface should be heavily revised to fit better in the style of Haskell.
Right now, it is still influenced by the non-monadic uniqueness style of Clean.
For example, the generation of identifiers (openId) is quit unsafe. In the Haskell
tradition we would use a monadic bind to name widgets.  ie.

>  w <- window []

instead of

>   w <- openId
>   openWindow ... [ WindowId w, ...]
This issue has nothing to do with monads, but is rather a design decision how to identify GUI elements. One particular disadvantage of the
w <- window []

style is that GUI creation is an (opaque) action, rather than a first-class description of the GUI. Identification values become available only after creation of GUI elements, which is less convenient than knowing them beforehand. The only 'danger' is forgetting to associate the identification value with the window, but the same problem exists with the other style:
w <- window []          -- window identified by w
...
close w                 -- window identified by w destroyed
...
setTitle w "Hi there"   -- unbound

Also, if you do prefer the binding style, it is easily added to Object I/O:
window :: IO WindowID
window = do {
            w <- openId
            window [WindowId w]
            return w
         }

Other things are the widget attributes that are specified using constructors. A more Haskellish
style
would use function names instead of constructors (as to be able to abstract from them) and use type
classes for grouping them (as to prevent using illegal attributes on a certain widget). i.e.

>  w <- window [title =: "My window" ]

instead of

>   w <- openId
>   openWindow ... [ WindowId w,  WindowTitle w...]
Window titles are mandatory in Object I/O, so the excerpt should read:
w <- openId
openWindow ... (Window "My window" [WindowId w])

The same argument applies here as above: data constructors are more 'first-class' than functions because one can do pattern-matching on them. Also, it is more general, as the elegant TkGofer style is built easily on top of it. For Object I/O devotees, it could be done as follows (in Clean):
// The class that fixes the relation between widget and attribute:
class Atts gui att where
    addAtt :: (gui .ls .pst) (att *(.ls,.pst)) -> gui .ls .pst
    getAtt :: (gui .ls .pst)                   -> att *(.ls,.pst)

// 'Lift' current attribute data constructors to type constructors:
::  WindowViewSize st = WindowViewSize` Size
::  WindowHScroll  st = WindowHScroll`  ScrollFunction

/* Instantiate the proper relations (note that view size and scroll bar
   are proper Window attributes, but for Dialogs only view size is valid.
*/
instance Atts (Window c) WindowViewSize | Controls c where ...
instance Atts (Window c) WindowHScroll  | Controls c where ...
instance Atts (Dialog c) WindowViewSize | Controls c where ...

// Convenient shorthand for addAtt:
(<==) infixl :: (gui .ls .pst) (att *(.ls,.pst))
            -> gui .ls .pst | Atts gui att
(<==) w a = addAtt w a

// Now one can set size and scroll attribute for a window...
w  = Window "Hi there" NilLS []
     <== WindowViewSize` {w=100,h=200}
      <== WindowHScroll` (stdScrollFunction Horizontal 100)
// ...and *only* the size for a dialog...
d1 = Dialog "Hi there" NilLS [] <== WindowViewSize` {w=100,h=200}
// ...but setting scrollbar won't type check...
d2 = Dialog "Hi there" NilLS [] <== WindowHScroll`
                                      (stdScrollFunction Horizontal 100)

This is basically what I am trying to do in the GIO library. However, even than, there
are still tons of other design decisions to make, I wonder whether consensus can ever
be reached.

All the best,
    Daan.
The above is not a critique on Port or GIO (honest!). I just wanted to explain part of the design reasons for Object I/O and show that it supports elegant ideas such as advocated by Daan.

Regards,
Peter