[GUI] Re: Know you backends

Peter Achten peter88@cs.kun.nl
Mon, 03 Feb 2003 16:38:50 +0100


--=====================_3352244==_.ALT
Content-Type: text/plain; charset="us-ascii"; format=flowed

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
>    * Offer as much type safety as possible without sacrificing 
> flexibility or give incomprehensible type errors. That's why GIO doesn't 
> use multiple parameter type classes to to implement attributes as in your 
> example :-). This is also what I like ObjectIO -- it uses little 
> overloading (but a fairly difficult GUI type).
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.
>    * Identify entities by value instead of by ID.
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.
>    * Not offer a model for structuring state but stay in the IO monad and 
> use simple mutable variables. Even though a model like that of ObjectIO 
> is convenient, I believe this belongs to a higher-level library.
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.
>    * Be fully dynamic -- each attribute should be changeable later (if 
> sensible), like layout, titles and event handlers. The advantage of 
> having attributes that can be set or read at any time, is that we don't 
> need to double functionality, like WindowViewDomain, getWindowViewDomain, 
> setWindowViewDomain, ControlViewDomain, setControlViewDomain and 
> getControlViewDomain. For a user we just have an attribute "domain" that 
> can be get or set.
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

--=====================_3352244==_.ALT
Content-Type: text/html; charset="us-ascii"

<html>
At 18:36 31-1-03 +0100, Daan Leijen wrote:<br>
<blockquote type=cite cite><font face="arial" size=2>Dear
Peter</font><br>
&nbsp;
<dl>
<dd>This issue has nothing to do with monads, but is rather a design
decision how to identify GUI elements. One particular disadvantage of the
<tt>
<dd>&nbsp;&nbsp; w &lt;- window []<br>
<br>
</tt>
<dd>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:<tt>
<dd>w &lt;- window
[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- window
identified by w 
<dd>... 
<dd>close
w&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-- window identified by w destroyed 
<dd>... 
<dd>setTitle w &quot;Hi there&quot;&nbsp;&nbsp; -- unbound
</dl><br>
</tt>&nbsp;<br>
<font face="arial" size=2>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</font><br>
<font face="arial" size=2>wrong widget. Each widget is later accessed
with an untyped ID, that may be connected</font><br>
<font face="arial" size=2>to a completely different widget kind.&nbsp;
With the monadic style, not an identifier</font><br>
<font face="arial" size=2>is returned but the typed entity itself and
thus all further access is also checked.</font></blockquote>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.
<br>
<br>
<br>
<blockquote type=cite cite>In this respect, I believe that a medium-level
library should<br>
<tt></tt>
<ul>
<li>Offer as much type safety as possible without sacrificing flexibility
or give incomprehensible type errors. That's why GIO doesn't use multiple
parameter type classes to to implement attributes as in your example :-).
This is also what I like ObjectIO -- it uses little overloading (but a
fairly difficult GUI type). </blockquote>
</ul>
<dl>
<dd>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. <blockquote type=cite cite>
</dl>
<ul>
<li>Identify entities by value instead of by ID. </blockquote>
</ul>
<dl>
<dd>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.
<blockquote type=cite cite>
</dl>
<ul>
<li>Not offer a model for structuring state but stay in the IO monad and
use simple mutable variables. Even though a model like that of ObjectIO
is convenient, I believe this belongs to a higher-level library.
</blockquote>
</ul>
<dl>
<dd>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.<blockquote type=cite cite>
</dl>
<ul>
<li>Be fully dynamic -- each attribute should be changeable later (if
sensible), like layout, titles and event handlers. The advantage of
having attributes that can be set or read at any time, is that we don't
need to double functionality, like
<font face="Courier, Courier">WindowViewDomain, getWindowViewDomain,
setWindowViewDomain, ControlViewDomain, setControlViewDomain
</font>and<font face="Courier, Courier"> getControlViewDomain. For a user
we just have an attribute &quot;domain&quot; that can be get or
set.</font></blockquote>
</ul>
<dl>
<dd>I agree on fully dynamic, and so does Object I/O, it just doesn't use
classes to organize these functions.<br>
<br>
<blockquote type=cite cite><tt><font face="arial" size=2>
<dd>The &quot;dynamic&quot; 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. </font></tt><pre>
<dd>&gt; do w &lt;- window [title =: &quot;Demo&quot;]

<dd>&gt;&nbsp;&nbsp;&nbsp; q &lt;- button [text =: &quot;Quit&quot;, on
command =: close w]

<dd>&gt;&nbsp;&nbsp;&nbsp; set w [layout =: center
q]</pre><font face="Courier New, Courier"></font><tt><font face="arial" size=2>
<dd>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 &lt;&lt;&lt; q), or when a
button</font></tt><tt><font face="arial" size=2>
<dd>created in some window is layed out in
another?)</font></tt></blockquote>
<dd>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?
<dl><tt>
<dd>do w1 &lt;- window [title =: &quot;A&quot;]
<dd>&nbsp;&nbsp; w2 &lt;- window [title =: &quot;B&quot;]
<dd>&nbsp;&nbsp; b1 &lt;- button [text =: &quot;Hi&quot;] 
<dd>&nbsp;&nbsp; set w1 [layout =: center b1]
<dd>&nbsp;&nbsp; set w2 [layout =: center b1]<br>
<br>
</tt>
</dl>
<dd>Can <tt>b </tt>be in two windows <tt>w1 </tt>and <tt>w2 </tt>at the
same time?<br>
<br>

</dl>Regards,<br>
Peter<br>
</html>

--=====================_3352244==_.ALT--