At 18:36 31-1-03 +0100, Daan Leijen wrote:
Dear Peter
 
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

 
There is more to this. Since ID's are untyped, it happened to me a few times that I attached the wrong id to the
wrong widget. Each widget is later accessed with an untyped ID, that may be connected
to a completely different widget kind.  With the monadic style, not an identifier
is returned but the typed entity itself and thus all further access is also checked.
Object I/O can easily be extended with typed identification values, in the same way as has been done for receivers (RId m) and (R2Id m r). The binding of typed identification value and the GUI object is at the data constructor.


In this respect, I believe that a medium-level library should
I agree that we should obtain as much type safety as possible. The problem is that more detailed types sometimes hamper expressiveness. Consider for instance a function that returns the identification values of all GUI elements in a window. If these are all typed according to the different type of GUI elements (text input fields have different types than buttons, and so on), then the type of this function is not as straightforward as one might hope.
I contend that the Object I/O way of handling GUI creation in two steps is more flexible than only offering creation actions for reasons mentioned in my earlier e-mail. In this set-up using IDs is symmetric, which isn't the case with the action-creation set-up.
Your first sentence is a contradiction in terms. However, I agree that a medium-level library should try to support as many higher-level libraries as possible. My guess is that this bit will prove to be the hardest part to design well.
I agree on fully dynamic, and so does Object I/O, it just doesn't use classes to organize these functions.

The "dynamic" ness of the library is also used to circumvent the problem that one wants to refer to a window before it is created, for example while specifying the layout of buttons in a window. In GIO, the layout can be set later, after the creation of the child controls.
> do w <- window [title =: "Demo"]
>    q <- button [text =: "Quit", on command =: close w]
>    set w [layout =: center q]
Same story for event handlers. I am not sure though how inconvenient this can be when creating larger applications but I feel that the extra type safety is worth the inconvenience. (Btw, layout is another dark area: what does it mean for example when a button is put next to itself (q <<< q), or when a button
created in some window is layed out in another?)
I must confess that I don't quite get your argument of circumventing the 'future reference problem'. Do you mean with the dark area something like the following?
do w1 <- window [title =: "A"]
   w2 <- window [title =: "B"]
   b1 <- button [text =: "Hi"]
   set w1 [layout =: center b1]
   set w2 [layout =: center b1]

Can b be in two windows w1 and w2 at the same time?

Regards,
Peter