Oh, cheers!&nbsp; Newtype deriving is more general than I expected.&nbsp; Thanks for the comment.<br><br>I&#39;ve requested a hackage account, so I expect it to be there shortly :-)<br><br>cheers,<br>Fraser.<br><br><div class="gmail_quote">
On Mon, Feb 16, 2009 at 9:12 PM, Ryan Ingram <span dir="ltr">&lt;<a href="mailto:ryani.spam@gmail.com">ryani.spam@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Tiny code-review comment:<br>
<br>
&gt; data Style = Style [(String, StyleValue)]<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;deriving (Read, Show)<br>
<br>
&gt; instance Monoid Style where<br>
&gt; &nbsp; &nbsp;mempty = Style []<br>
&gt; &nbsp; &nbsp;mappend (Style xs) (Style ys) = Style (xs ++ ys)<br>
<br>
=&gt;<br>
<br>
&gt; {-# LANGUAGE GeneralizedNewtypeDeriving #-}<br>
&gt;<br>
&gt; newtype Style = Style [(String, StyleValue)]<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;deriving (Read, Show, Monoid)<br>
<br>
Also, put it on hackage! :) &nbsp;It looks pretty cool.<br>
<font color="#888888"><br>
 &nbsp;-- ryan<br>
</font><div class="Ih2E3d"><br>
2009/2/16 Fraser Wilson &lt;<a href="mailto:blancolioni@gmail.com">blancolioni@gmail.com</a>&gt;:<br>
</div><div><div></div><div class="Wj3C7c">&gt; Since I&#39;m congenitally lazy, and writing a GUI by hand in the IO monad is<br>
&gt; ... not what I expect from a beautiful program, and because what I often<br>
&gt; need is a GUI that manipulates a state, and because I don&#39;t understand<br>
&gt; arrows, and having been intrigued by a recent cafe thread, I threw together<br>
&gt; a prototype GUI library with the following features:<br>
&gt;<br>
&gt; &nbsp; - the GUI is defined on three levels: gadgets, widgets and styles<br>
&gt; &nbsp; - gadgets are functions on a state<br>
&gt; &nbsp; - widgets are data structures which define the layout<br>
&gt; &nbsp; - styles are ways to modify the appearance of widgets<br>
&gt;<br>
&gt; The following quick example shows a text box and a button. &nbsp;Clicking on the<br>
&gt; button reverses the text in the text box.<br>
&gt;<br>
&gt;&gt; module Main where<br>
&gt;<br>
&gt;&gt; import Barrie<br>
&gt;<br>
&gt;&gt; demoWidget :: Widget<br>
&gt;&gt; demoWidget = vbox [ui &quot;demo entry&quot; textBox,<br>
&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ui &quot;demo command&quot; (labelButton &quot;click me&quot;)]<br>
&gt;<br>
&gt;&gt; type DemoState = String<br>
&gt;<br>
&gt;&gt; type DemoGadget = Gadget DemoState<br>
&gt;<br>
&gt;&gt; demoGUI :: DemoGadget<br>
&gt;&gt; demoGUI = localG &quot;demo gui&quot; [editorG &quot;demo entry&quot; id const,<br>
&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;commandG &quot;demo command&quot; reverse]<br>
&gt;<br>
&gt;&gt; main = gtkMain demoGUI demoWidget &quot;Hello, world&quot;<br>
&gt;<br>
&gt; Two gadgets are used:<br>
&gt;<br>
&gt; editorG :: String -&gt; (a -&gt; b) -&gt; (b -&gt; a -&gt; a) -&gt; Gadget a<br>
&gt; commandG :: String -&gt; (a -&gt; a) -&gt; Gadget a<br>
&gt;<br>
&gt; The editor gadget can show a value from a state, and update a state with a<br>
&gt; value. &nbsp;The command gadget can transform a state to a new state. &nbsp;gtkMain<br>
&gt; connects the gadgets to a widget, which specifies layout using the vbox,<br>
&gt; attaching the editor gadget to a text box, and the command gadget to a<br>
&gt; button.<br>
&gt;<br>
&gt; Well, that&#39;s all pretty trivial. &nbsp;The key thing for me was that I can easily<br>
&gt; slap a GUI onto the the front of a class of applications, which happen to be<br>
&gt; the sort of applications I&#39;ve been writing lately. &nbsp;Also, arbitrary parts of<br>
&gt; the GUI can respond to things that happen miles away, without really having<br>
&gt; to worry about it too much. &nbsp;In barrie-0.1 and 0.2, which used stream-based<br>
&gt; approaches, the problem of getting state from one end of the application to<br>
&gt; the other was non-trivial.<br>
&gt;<br>
&gt; I&#39;ll sketch another quick example:<br>
&gt;<br>
&gt;&gt; data BridgeGame = ...<br>
&gt;<br>
&gt; And a bunch of things you can do with the state:<br>
&gt;<br>
&gt;&gt; makeBid :: Bid -&gt; BridgeGame -&gt; BridgeGame<br>
&gt;&gt; playCard :: Card -&gt; BridgeGame -&gt; BridgeGame<br>
&gt;<br>
&gt; For bidding, each bid is represented by a gadget:<br>
&gt;<br>
&gt;&gt; bidG :: Bid -&gt; Gadget BridgeGame<br>
&gt;&gt; bidG bid = enabled (bidOK bid) $ CommandG (show bid) (makeBid bid)<br>
&gt;<br>
&gt; &#39;enabled&#39; switches the gadget on if its first argument returns true when<br>
&gt; applied to the current state. &nbsp;However, the decision about what to do with a<br>
&gt; disabled gadget is made by its corresponding widget.<br>
&gt;<br>
&gt; We get one button for each bid:<br>
&gt;<br>
&gt;&gt; biddingG :: Gadget BridgeGame<br>
&gt;&gt; biddingG = localG &quot;bidding&quot; (map bidG allBids)<br>
&gt;<br>
&gt; And they can be displayed in any old order using a widget:<br>
&gt;<br>
&gt;&gt; biddingW :: Widget<br>
&gt;&gt; biddingW = vbox (map suitBids [Club, Diamond, Heart, Spade] ++ [ntBids])<br>
&gt;&gt; &nbsp; &nbsp;where suitBids suit = hbox $ map (bidButton . flip Bid suit) [1 .. 7]<br>
&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ntBids = hbox $ map (bidButton . NT) [1 .. 7]<br>
&gt;&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bidButton bid = ui (show bid) $ labelButton (show bid)<br>
&gt;<br>
&gt; (You&#39;re right, double, redouble and pass are not represented. &nbsp;They make the<br>
&gt; lines too long).<br>
&gt;<br>
&gt; Screenshot here: <a href="http://thewhitelion.org/images/4D.png" target="_blank">http://thewhitelion.org/images/4D.png</a><br>
&gt;<br>
&gt; I&#39;ve just bid four diamonds, so everything lower than that is automatically<br>
&gt; disabled.<br>
&gt;<br>
&gt; Currently, Barrie implements buttons, text boxes, labels,<br>
&gt; vertical/horizontal layout, single-column lists and drop lists. &nbsp;It current<br>
&gt; uses Gtk2hs for rendering, but it&#39;s GUI-agnostic (in fact, the first<br>
&gt; renderer was putStrLn/getLine).<br>
&gt;<br>
&gt; You can have a look by using darcs:<br>
&gt; &nbsp; &nbsp;darcs get <a href="http://thewhitelion.org/darcs/barrie" target="_blank">http://thewhitelion.org/darcs/barrie</a><br>
&gt;<br>
&gt; Or get the tarball at<br>
&gt; <a href="http://thewhitelion.org/haskell/barrie-0.3.0-src.tar.gz" target="_blank">http://thewhitelion.org/haskell/barrie-0.3.0-src.tar.gz</a><br>
&gt;<br>
&gt; One note: this is not intended to be a theoretically sound approach, merely<br>
&gt; a way of getting something done quickly. &nbsp;I would expect it to be most<br>
&gt; useful in putting a GUI front-end onto an existing application, in<br>
&gt; particular, an application that is driven by user actions which update a<br>
&gt; state; e.g. a calculator, a bridge game, a 4th edition D&amp;D character creator<br>
&gt; (but that leads to a critical mass of nerdiness, so it&#39;s off the table for<br>
&gt; now)<br>
&gt;<br>
&gt; cheers,<br>
&gt; Fraser.<br>
&gt;<br>
&gt; --<br>
&gt; <a href="http://thewhitelion.org/mysister" target="_blank">http://thewhitelion.org/mysister</a><br>
&gt;<br>
</div></div><div><div></div><div class="Wj3C7c">&gt; _______________________________________________<br>
&gt; Haskell-Cafe mailing list<br>
&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
&gt;<br>
&gt;<br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br><a href="http://thewhitelion.org/mysister">http://thewhitelion.org/mysister</a><br>