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.
 
The other problem (closing and accessing) seems only solvable within a higher-level framework.
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.
 
Off course it does :-) Since ObjectIO is in this respect on a lower-level, GIO could be implemented on top of Object/IO -- that is also why one could implement the attribute approach on top of the ObjectIO constructors. The whole issue is probably more of a question of what should be part of a medium-level GUI library (and what not).  
 
In this respect, I believe that a medium-level library should
> class HasDomain w where
>   domain :: Attr w Size
> instance HasDomain Window
> instance HasDomain CompoundControl
>
> get :: w -> Attr w a -> IO a
> set :: w -> [Prop w] -> IO ()
> (=:) :: Attr w a -> a -> Prop w
>
> test = do w <- window []
>           set w [domain =: Size 100 100]
>           ....
(btw. Allthough fairly straightforward, this nice attribute stuff is invented (I think) by Koen Claessen -- I read his lecture notes).
 
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?)
All the best,
  Daan.
 
ps. I have been thinking about more 'improvements' for the (haskell?) ObjectIO library. For example, getting rid of state transformers in the GUI monad, like the GUIFun for example: "(ls,ps) -> GUI ps (ls,ps)". The idea is put every state in a "UI ls ps a" monad with "getLS :: UI ls ps ls"  etc. functions. I believe that the types become much easier to comprehend but it is a fairly extensive change. Maybe we should talk about this off-line some time.