[GUI] Re: Know you backends

Daan Leijen daanleijen@xs4all.nl
Fri, 31 Jan 2003 18:36:36 +0100


This is a multi-part message in MIME format.

------=_NextPart_000_00A5_01C2C957.AF965D40
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

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=20

     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=20
    ...=20
    close w                 -- window identified by w destroyed=20
    ...=20
    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). =20

In this respect, I believe that a medium-level library should
  a.. 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).
  b.. Identify entities by value instead of by ID.
  c.. 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.
  d.. 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.
> 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 ()> (=3D:) :: Attr w a -> a -> Prop w>> =
test =3D do w <- window []>           set w [domain =3D: 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.=20
> do w <- window [title =3D: "Demo"]>    q <- button [text =3D: "Quit", =
on command =3D: close w]>    set w [layout =3D: 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.
------=_NextPart_000_00A5_01C2C957.AF965D40
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2800.1126" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>Dear Peter</FONT></DIV>
<DIV style=3D"FONT: 10pt arial">&nbsp;</DIV>
<BLOCKQUOTE=20
style=3D"PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; =
BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
  <DIV type=3D"cite">This issue has nothing to do with monads, but is =
rather a=20
  design decision how to identify GUI elements. One particular =
disadvantage of=20
  the <BR><TT></TT></DIV>
  <DIV type=3D"cite"><TT>&nbsp;&nbsp; w &lt;- window =
[]<BR><BR></TT>style is that=20
  GUI creation is an (opaque) action, rather than a first-class =
description of=20
  the GUI. Identification values become available only after creation of =
GUI=20
  elements, which is less convenient than knowing them beforehand. The =
only=20
  'danger' is forgetting to associate the identification value with the =
window,=20
  but the same problem exists with the other style:<BR></DIV>
  <DL><TT>
    <DD>w &lt;- window []&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --=20
    window identified by w=20
    <DD>...=20
    <DD>close=20
    =
w&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp;&nbsp;&nbsp;&nbsp;=20
    -- window identified by w destroyed=20
    <DD>...=20
    <DD>setTitle w "Hi there"&nbsp;&nbsp; -- =
unbound</DD></DL></BLOCKQUOTE>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>There is more to this. Since ID's are =
untyped, it=20
happened to me a few times that I attached the wrong id to =
the</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>wrong widget. Each widget is later =
accessed with an=20
untyped ID, that may be connected</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>to a completely different widget =
kind.&nbsp; With=20
the monadic style, not an identifier</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>is returned but the typed entity itself =
and thus=20
all further access is also&nbsp;checked.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>The other problem (closing and =
accessing) seems=20
only solvable within a higher-level =
framework.</FONT></DIV></TT><TT><FONT=20
face=3DArial size=3D2>
<BLOCKQUOTE=20
style=3D"PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; =
BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
  <DIV>The above is not a critique on Port or GIO (honest!). I just =
wanted to=20
  explain part of the design reasons for Object I/O and show that it =
supports=20
  elegant ideas such as advocated by Daan.</DIV>
  <DIV>&nbsp;</DIV></BLOCKQUOTE>
<DIV><FONT face=3DArial size=3D2>Off course it does :-) Since ObjectIO =
is in this=20
respect on a lower-level, GIO could be implemented on top of Object/IO =
-- that=20
is also </FONT><FONT face=3DArial size=3D2>why&nbsp;one could implement =
the=20
attribute approach on top of the ObjectIO constructors. The whole issue=20
</FONT>is probably more of a question of what should be part of a =
medium-level=20
GUI library (and what not).&nbsp;&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>In this respect, I believe that&nbsp;a medium-level library =
should</DIV>
<UL>
  <LI>Offer as much type safety as possible without sacrificing =
flexibility or=20
  give incomprehensible type errors. That's why GIO doesn't use multiple =

  parameter type classes to to implement attributes as in your example =
:-). This=20
  is also&nbsp;what I like ObjectIO&nbsp;-- it uses little overloading =
(but=20
  a&nbsp;fairly difficult GUI type).</LI>
  <LI>Identify entities by value instead of by ID.</LI>
  <LI>Not offer a model for structuring state but stay in the IO monad =
and use=20
  simple mutable variables. Even though a model like that of ObjectIO is =

  convenient, I believe&nbsp;this belongs to a higher-level =
library.</LI>
  <LI>Be fully dynamic -- each attribute should be changeable later (if=20
  sensible), like layout, titles and event handlers. The advantage of =
having=20
  attributes that can be set or read at any time, is that we don't need =
to=20
  double functionality, like <FONT face=3DCourier>WindowViewDomain,=20
  getWindowViewDomain, setWindowViewDomain, ControlViewDomain,=20
  setControlViewDomain <FONT face=3DArial>and</FONT>=20
  getControlViewDomain.&nbsp;</FONT> For a user we just have an =
attribute=20
  "domain" that can be get or set.</LI></UL></FONT></TT>
<BLOCKQUOTE><PRE>&gt; class HasDomain w where<BR>&gt;&nbsp;&nbsp; domain =
:: Attr w Size <BR>&gt; instance HasDomain Window<BR>&gt; instance =
HasDomain CompoundControl<BR>&gt;<BR>&gt; get :: w -&gt; Attr w a -&gt; =
IO a<BR>&gt; set :: w -&gt; [Prop w] -&gt; IO ()<BR>&gt; (=3D:) :: Attr =
w a -&gt; a -&gt; Prop w<BR>&gt;<BR>&gt; test =3D do&nbsp;w &lt;- window =
[]<BR>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
set w [domain =3D: Size 100 =
100]<BR>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
....</PRE><FONT=20
  face=3DArial><TT>
  <DIV><FONT face=3DArial size=3D2>(btw. Allthough fairly =
straightforward, this nice=20
  attribute stuff is invented (I think) by Koen Claessen -- I =
read&nbsp;his=20
  lecture notes).</FONT></DIV>
  <DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
  <DIV><FONT face=3DArial size=3D2>The "dynamic" ness of the library is =
also used to=20
  circumvent the problem that one wants to refer to a window before it =
is=20
  created, for example while specifying the layout of buttons in a =
window. In=20
  GIO, the layout can be set later, after the creation of the child =
controls.=20
  </FONT></DIV></FONT></TT><PRE>&gt; do w &lt;- window [title =3D: =
"Demo"]<BR>&gt;    q &lt;- button [text =3D: "Quit", on command =3D: =
close w]<BR>&gt;    set w [layout =3D: center q]</PRE>
  <DIV><TT><FONT face=3DArial size=3D2>Same story for event handlers. I =
am not sure=20
  though how inconvenient this can be when creating larger applications=20
  </FONT></TT><TT><FONT face=3DArial size=3D2>but I feel that the extra =
type safety=20
  is worth the inconvenience. (Btw, layout is another dark area: what =
does it=20
  mean for example when a button is put next to itself (q &lt;&lt;&lt; =
q), or=20
  when a button</FONT></TT></DIV>
  <DIV><TT><FONT face=3DArial size=3D2>created in some window is layed =
out in=20
  another?)</FONT></TT></DIV></BLOCKQUOTE>
<DIV><TT><FONT face=3DArial size=3D2>All the best,</FONT></TT></DIV>
<DIV><TT><FONT face=3DArial size=3D2>&nbsp; Daan.</FONT></TT></DIV>
<DIV><TT><FONT face=3DArial size=3D2></FONT></TT>&nbsp;</DIV>
<DIV><TT><FONT face=3DArial size=3D2>ps. I have been thinking about more =

'improvements' for the (haskell?) ObjectIO library. For example, getting =
rid of=20
state transformers in the GUI monad, like the GUIFun for example: =
"(ls,ps) -&gt;=20
GUI ps (ls,ps)". The idea is put every state&nbsp;in a "UI ls ps a" =
monad with=20
"getLS :: UI ls ps ls"&nbsp; etc. functions. I believe that the types =
become=20
much </FONT></TT><TT><FONT face=3DArial size=3D2>easier to comprehend =
but it is a=20
fairly extensive change. Maybe we should talk about this off-line some=20
time.</FONT></TT></DIV></BODY></HTML>

------=_NextPart_000_00A5_01C2C957.AF965D40--