[GUI] Some random thought of my own

Nick Name nick.name@inwind.it
Thu, 6 Mar 2003 03:17:54 +0100


This is a multi-part message in MIME format.

--Multipart_Thu__6_Mar_2003_03:17:54_+0100_0833af00
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit

DISCLAIMER: I don't pretend to have had new ideas, nor that what I say
here is correct or good. It is premature to post my code here, I have
not studied everything I wanted to, but since the discussion is up and
running, I have to :)

On Wed, 5 Mar 2003 16:13:03 -0800 (PST)
David Sankel <camio@yahoo.com> wrote:

> 
>  I propose we use the GIO/Object IO style.  Does anyone
>  have any other preferred styles that I'm missing? 
>  Which style do you prefer?

There are others. First, you can define widget and combinators as purely
functional values, and really "create" widgets only in the runGUI (or
whatever you'd name it) operation.

I have a working example, which I wrote just to classify all my thougts,
in wich the simple program proposed by John Meacham looks like:

main =  do
	(w,b) <- managedButton "Bye"

	Application a <- runGUI (window (vBox [label "Hello World!",w]))

	processOutput_ (buttonClicked b) 
                           [putInput (buttonLabel b) "Goodbye",
                            putInput a ()]

managedButton :: String -> IO (Widget,Button)
button :: String -> Widget
label :: String -> Widget

...and so on. I wrote it to test an idea I have about changing the
state, note how the Widget type is purely functional (it encapsulates
the IO needed to create the widget). I attach my code, wich is for
Gtk2hs, in case someone wants to read it.

Let's come back to the topic. I apologize for my bad english, as usual,
and for the length of this e-mail.


=======
1. How is the local state of a widget changed?
   
   Basically, the world is divided between people that like monadic   
operations, and people that prefer streams. Manuel Chakravarty in his
"Ports" library combines the two, even if he is more biased to streams.
When it's time to choose between two different approaches, which prove
both useful, I prefer when I can have both!

We can do a more fine-grained work by separating the read and write
operations (thus avoiding a runtime error implementing the write
operation of read-only properties). This leads to the following
definition for a variable:

data Input a = Input { putInput :: a -> IO () }

data Output a = Output { readOutput :: IO a,
		         waitOutput :: IO a,  -- wait for a state change
		         listenOutput :: IO [a] }

data Var a = Var { varInput :: Input a,
		   varOutput :: Output a }

We can define in a purely functional way the map operation on an output,
and many transformations on inputs and outputs, as it's done in FRAN;
(There are issues to consider, such as "closing" the Var; I leave it for
tomorrow and for more expert people; also, someone willing to speak
about arrows and Var?).

Using this idea, an handler for a button has type "Output ()", or at
least contains this type.

You can also install a callback on state changes, with the operations:

  onOutput :: Output a -> (a -> IO b) -> IO ()
  onOutput o m = forkIO ( listenOutput o >>= mapM_ m) >> return ()
 
  onVar = onOutput . varOutput

(BTW, threads in GHC *are* lightweight! I tested listening to thousands
of Vars simultaneously without troubles on a celeron some month ago)

And, besides, separating input and output you can give a simple
interface to many things, for example input devices are "Output"s from
the point of view of the application.

NOTE:
With Ports, or Vars or Attrs, one can easily make a variable persistent.
I think this hasn't been spotted, but deserves more attention!


=====
2. How is a widget created?
Everyone seems to agree on

      createSomething :: SomethingConfiguration -> IO Something

but this clutters the code with many unneeded monadic operations. We   
can use data constructors when needed, or postpone the creation in a   
"runGUI" function and just compose the needed actions: notice how  
readable is


       runGUI (window (vBox [label "Hello World!",w])

due to the absence of monadic operators where they are not needed, if
compared to a standard monadic sequence.

In "managedButton" (the creation of w), I think monadic operator ARE
needed because we need to create an "entaglement" between the button
data and the IO operation that will create it, but I am not completely
sure.

=====
3. How is the configuration data passed to a widget? This opens many
questions, and surely many other that I don't mention here.

   - We could have two constructors for a button, one "a la GIO" and one
     with standard function syntax, wich is more readable in some cases.
        Example:
   
          button "Hi all"

       versus
 
          button [label=:"Hi all"]
       
       Of course, this is not Daan Leijen's fault: it's difficult to    
   handle defaults to avoid entering ten or twelve configuration       
parameters. In my example, I don't care about a button being also       
a widget with size, for example. So I propose to give both the       
interfaces, one with only basic options and a functional form,      
another, more complex, like the one in GIO or with records.

   - Some subtyping trick with multiparameter type classes can make the
     operator =: accept properties for a generic, and apply them to a
     button, I think.

   - We need to consider the loading from resource files as a     
constructor, not everything is pragmatic. I think this is      not a big
issue.

   - I would like to know more about named widgets and their use.

   - We could just use record types, filling undefined fields with     
defaults in the constructor. This approach can easily live side by     
side with the GIO one.

   - We could just use implicit parameters, but I don't think this would
     feel comfortable.

=====

I hope someone is interested...

Vincenzo
--Multipart_Thu__6_Mar_2003_03:17:54_+0100_0833af00
Content-Type: application/octet-stream;
 name="GUI.hs"
Content-Disposition: attachment;
 filename="GUI.hs"
Content-Transfer-Encoding: base64

LS0gVGhpcyBpcyBqdXN0IGEgc2ltcGxlIGV4YW1wbGUgdG8gb3JnYW5pemUgc29tZSByYW5kb20g
dGhvdWdodC4KLS0gT2YgY291cnNlLCBHSU8gaWRlYXMgY2FuIGJlIGNvbWJpbmVkIHdpdGggdGhl
c2UuCgotLSBUaGVyZSBhcmUgdHdvIHRoaW5ncyBJIHdhbnQgcGVvcGxlIHRvIG5vdGljZToKLS0K
LS0gMS4gV2lkZ2V0cyBhcmVuJ3QgbmVjZXNzYXJpbHkgcHJvZHVjZWQgYnkgSU8gYWN0aW9ucywg
c2luY2UgdGhleQotLSBDT05UQUlOIGFuIElPIGFjdGlvbi4KLS0KLS0gMi4gVGhlIHVzZSBvZiBW
YXJzIHRvIG1vZGVsIHRoZSBzdGF0ZSBvZiB0aGUgd2lkZ2V0cy4KCm1vZHVsZSBHVUkgd2hlcmUK
CmltcG9ydCBEaXJlY3RvcnkKaW1wb3J0IHF1YWxpZmllZCBHdGsKCmltcG9ydCBJT1JlZgppbXBv
cnQgTW9uYWQKaW1wb3J0IFZhcgppbXBvcnQgQ29uY3VycmVudAppbXBvcnQgRXhjZXB0aW9uCgpp
bXBvcnQgcXVhbGlmaWVkIFN0cnVjdHMKCmRhdGEgQXBwbGljYXRpb24gPQogICAgQXBwbGljYXRp
b24geyBxdWl0IDo6IElucHV0ICgpIH0KCmRhdGEgQnV0dG9uID0gCiAgICBCdXR0b24geyBidXR0
b25DbGlja2VkIDo6IE91dHB1dCAoKSwKCSAgICAgYnV0dG9uTGFiZWwgOjogSW5wdXQgU3RyaW5n
IH0KCmRhdGEgTGFiZWwgPSBMYWJlbCB7IGxhYmVsTGFiZWwgOjogSW5wdXQgU3RyaW5nIH0KCmRh
dGEgV2luZG93ID0gV2luZG93IHsgd2luZG93V2lkZ2V0IDo6IElucHV0IFdpZGdldCB9CgpkYXRh
IFZCb3ggPSBWQm94IHsgdmJveFdpZGdldHMgOjogSW5wdXQgW1dpZGdldF0gfQoKZGF0YSBXaWRn
ZXQgPSBmb3JhbGwgYSAuIEd0ay5XaWRnZXRDbGFzcyBhID0+IFdpZGdldCAoSU8gYSkKCm1hbmFn
ZWRCdXR0b24gOjogU3RyaW5nIC0+IElPIChXaWRnZXQsQnV0dG9uKQptYW5hZ2VkQnV0dG9uIGxh
YmVsID0gZG8gCgkJICAgICB0ZXh0VmFyIDwtIHN0YXRlVmFyIGxhYmVsCgkJICAgICBjbGlja1Zh
ciA8LSBzdGF0ZVZhciAoKQoJCSAgICAgcmV0dXJuIChXaWRnZXQgKGRvCgkJCQkgICAgIGIgPC0g
R3RrLmJ1dHRvbk5ld1dpdGhMYWJlbCBsYWJlbAoJCQkJICAgICBHdGsub25DbGlja2VkIGIgKHB1
dFZhciBjbGlja1ZhciAoKSA+PiBHdGsud2lkZ2V0UXVldWVEcmF3IGIpCgkJCQkgICAgIG9uVmFy
IHRleHRWYXIgKEd0ay5idXR0b25TZXRMYWJlbCBiKQoJCQkJICAgICByZXR1cm4gYiksCgkJCSAg
ICAgQnV0dG9uIHsgYnV0dG9uQ2xpY2tlZCA9IHZhck91dHB1dCBjbGlja1ZhciwKCQkJCSAgICAg
IGJ1dHRvbkxhYmVsID0gdmFySW5wdXQgdGV4dFZhciB9KQoKCmJ1dHRvbiA6OiBTdHJpbmcgLT4g
V2lkZ2V0CmJ1dHRvbiBsYWJlbCA9IFdpZGdldCAoR3RrLmJ1dHRvbk5ld1dpdGhMYWJlbCBsYWJl
bCkKCmxhYmVsIDo6IFN0cmluZyAtPiBXaWRnZXQKbGFiZWwgbCA9IFdpZGdldCAoR3RrLmxhYmVs
TmV3IChKdXN0IGwpKQoKbWFuYWdlZExhYmVsIDo6IFN0cmluZyAtPiBJTyAoV2lkZ2V0LExhYmVs
KQptYW5hZ2VkTGFiZWwgbCA9IGRvCgkJIHYgPC0gc3RhdGVWYXIgbAoJCSByZXR1cm4gKFdpZGdl
dCAoZG8KCQkJCSBsMSA8LSBHdGsubGFiZWxOZXcgKEp1c3QgbCkJCQkJIAoJCQkJIG9uVmFyIHYg
KEd0ay5sYWJlbFNldFRleHQgbDEpCgkJCQkgcmV0dXJuIGwxKSwKCQkJIExhYmVsIHsgbGFiZWxM
YWJlbCA9IHZhcklucHV0IHYgfSkKCnZCb3ggOjogW1dpZGdldF0gLT4gV2lkZ2V0CnZCb3ggbCA9
IAogICAgV2lkZ2V0IChkbyAKCSAgICB2YiA8LSBHdGsudkJveE5ldyBGYWxzZSAwCgkgICAgbWFw
TV8gKFwgKFdpZGdldCB4KSAtPiAoZG8KCQkJCSAgICB5IDwtIHgKCQkJCSAgICBHdGsuY29udGFp
bmVyQWRkIHZiIHkKCQkJCSAgICBHdGsud2lkZ2V0U2hvdyB5KSkgbAoJICAgIHJldHVybiB2YikK
CmhCb3ggOjogW1dpZGdldF0gLT4gV2lkZ2V0CmhCb3ggbCA9IAogICAgV2lkZ2V0IChkbyAKCSAg
ICBoYiA8LSBHdGsuaEJveE5ldyBGYWxzZSAwCgkgICAgbWFwTV8gKFwgKFdpZGdldCB4KSAtPiAo
ZG8KCQkJCSAgICB5IDwtIHgKCQkJCSAgICBHdGsuY29udGFpbmVyQWRkIGhiIHkKCQkJCSAgICBH
dGsud2lkZ2V0U2hvdyB5KSkgbAoJICAgIHJldHVybiBoYikKCndpbmRvdyA6OiBXaWRnZXQgLT4g
V2lkZ2V0CndpbmRvdyAoV2lkZ2V0IHcpID0KICAgIFdpZGdldCAoZG8KCSAgICB4IDwtIHcKCSAg
ICB3aW4gPC0gR3RrLndpbmRvd05ldwoJICAgIEd0ay5jb250YWluZXJBZGQgd2luIHgKCSAgICBH
dGsud2lkZ2V0U2hvdyB4CgkgICAgR3RrLndpZGdldFNob3cgd2luCgkgICAgcmV0dXJuIHdpbikK
CndoaWxlTSBjIGEgPSBkbwogICAgICAgICAgICAgYiA8LSBjCgkgICAgIGlmIGIgCgkJdGhlbiBh
ID4+IHdoaWxlTSBjIGEgCgkJZWxzZSByZXR1cm4gKCkKCgotLSBEb24ndCBwYXkgYXR0ZW50aW9u
IHRvIHRoaXMgZnVuY3Rpb24sIHRoZXJlIGFyZSBiZXR0ZXIgd2F5cyB0byBkZWZpbmUgdGhpcywK
LS0gYnV0IGluIHNvbWUgb2NjYXNpb25zIEkgaGF2ZSBoYWQgdHJvdWJsZXMsIGFuZCB0aGlzIGlz
IHRoZSBiZXN0IHdvcmtpbmcgb24gCi0tIG15IHN5c3RlbSBieSBub3cuIE1vcmVvdmVyLCB0aGlz
IGlzIG5vdCBndGsyaHMgZmF1bHQgSSBiZWxpZXZlLgpydW5HVUkgOjogV2lkZ2V0IC0+IElPIEFw
cGxpY2F0aW9uCnJ1bkdVSSAoV2lkZ2V0IHcpID0KICAgIGRvIGZvcmtJTyAoZG8KCSAgICAgICBH
dGsuaW5pdEdVSQoJICAgICAgIHcKCSAgICAgICBkb250ZXhpdCA8LSBuZXdJT1JlZiBUcnVlCgkg
ICAgICAgd2hpbGVNIChyZWFkSU9SZWYgZG9udGV4aXQpCgkgICAgICAgIChkbwoJCSB0aHJlYWRE
ZWxheSAyMDAwMAoJCSB3aGlsZU0gKEd0ay5ldmVudHNQZW5kaW5nID4+PSByZXR1cm4gLiAoMDwp
KSAoR3RrLm1haW5JdGVyYXRpb25EbyBGYWxzZSA+Pj0KCQkJCQkJCSAgICAgICB3cml0ZUlPUmVm
IGRvbnRleGl0KSkpICAgICAgIAogICAgICAgcmV0dXJuIChBcHBsaWNhdGlvbiAoSW5wdXQgKFwg
KCkgLT4gR3RrLm1haW5RdWl0KSkpCg==

--Multipart_Thu__6_Mar_2003_03:17:54_+0100_0833af00
Content-Type: application/octet-stream;
 name="Var.hs"
Content-Disposition: attachment;
 filename="Var.hs"
Content-Transfer-Encoding: base64

LS0gU1VNTUFSWToKLS0KLS0gQSBtb2R1bGUgaW1wbGVtZW50aW5nIHRoZSAiSW5wdXQiLCAiT3V0
cHV0IiBhbmQgIlZhciIgZGF0YSB0eXBlcy4KLS0KLS0gQW4gSW5wdXQgY2FuIGJlIHdyaXR0ZW4g
dG8sIGFuIE91dHB1dCBjYW4gYmUgcmVhZCwgYnV0IHlvdSBjYW4gYWxzbwotLSB3YWl0IGZvciBh
IGNoYW5nZSBpbiB0aGUgdmFsdWUsIG9yIHJldHJpZXZlIHRoZSBsaXN0IG9mIGFsbCB2YWx1ZXMK
LS0gYXNzdW1lZC4gQSBWYXIgaXMgYSBjb21iaW5hdGlvbiBvZiBhbiBJbnB1dCBhbmQgYW4gT3V0
cHV0IHdpdGggdGhlCi0tIHNhbWUgdHlwZSBmb3IgdmFsdWVzLgoKLS0gSU5TUElSQVRJT046Ci0t
Ci0tIEZpcnN0IG9mIGFsbCwgdGhpcyBpcyBhbG1vc3QgdGhlIHNhbWUgdGhpbmcgb2YgTWFudWVs
IENoYWtyYXZhcnR5J3MgUG9ydHMKLS0gbGlicmFyeS4gVGhlIFBvcnRzIGxpYnJhcnkgaGFzIGEg
Z3JlYXQgaWRlYTogcHJvdmlkZSBib3RoIHRoZSBzdHJlYW0tYmFzZWQgCi0tIGFwcHJvYWNoIGFu
ZCB0aGUgbW9uYWRpYyBvbmUsIGxldCB0aGUgdXNlciBkZWNpZGUuCi0tCi0tIFNlY29uZDogRlJB
Ti4gSW4gdGhpcyBsaWJyYXJ5LCB5b3UgaGF2ZSBhIGNsZWFyIHNlcGFyYXRpb24gb2YKLS0gaW5w
dXRzIGFuZCBvdXRwdXRzLCBhbmQgYSBzZXQgb2YgcHVyZWx5IGZ1bmN0aW9uYWwgY29tYmluYXRv
cnMgdG8KLS0gY3JlYXRlIG5ldyBpbnB1dHMgYW5kIG91dHB1dHMgZnJvbSBleGlzdGluZyBvbmVz
LgoKLS0gQURWQU5UQUdFUzoKLS0gCi0tIEEgc2ltcGxlIGFwcHJvYWNoIHRvIChkaXNjcmV0ZWx5
KSB0aW1lLXZhcnlpbmcgdmFsdWVzLiAKLS0gQm90aCBjaGFubmVscyBhbmQgbXZhcnMgY291bGQg
YmUgc3Vic3VtZWQgKGJ1dCBzZWUgaXNzdWUgbi4gMiwgdGhlIHJlYWQgCi0tIG9wZXJhdGlvbiBo
YXMgbm8gbWVhbmluZyBvbiBjaGFucykuCi0tCi0tIFlvdSBjYW4gZWFzaWx5IGV4dGVuZCB0aGUg
c3RhdGUgb2YgYSBwcm9ncmFtLiBGb3IgZXhhbXBsZSwgYWZ0ZXIgaGF2aW5nIHdyaXR0ZW4KLS0g
dGhlIHByb2dyYW0sIHlvdSBjYW4gZGVjaWRlIHRvIG1ha2Ugc29tZSB2YXJpYWJsZSBwZXJzaXN0
ZW50IGluIGEgZGF0YWJhc2UuCi0tIFRoaXMgY291bGQgYmUgdXNlZnVsIGluIGNvbmp1bmN0aW9u
IHdpdGggZ2NvbmYsIGZvciBhIHByb2dyYW0ncyBjb25maWd1cmF0aW9uLgoKLS0gSVNTVUVTCi0t
IAotLSAxLgotLSBUbyBleGl0IGZyb20gdGhlIHN0YXRlIG9mIGJlaW5nIGEgdG95LCB0aGlzIGxp
YnJhcnkgbmVlZHMgdGhlIGFiaWxpdHkKLS0gdG8gY2xvc2Ugb3V0cHV0cywgYnV0IHRoaXMgaXMg
YSBwcm9ibGVtLCBzaW5jZSB0aGUgcmVhZCBvcGVyYXRpb24gYmVjb21lcwotLSB1bmRlZmluZWQu
Ci0tCi0tIDIuCi0tIFRoZXJlIG1pZ2h0IGJlIGNhc2VzIGluIHdpY2ggdGhlIHJlYWQgb3BlcmF0
aW9uIGhhcyBubyBtZWFuaW5nLCBpbiB3aWNoIHRoZSBuYW1lCi0tIG9mICJ3aXJlcyIgY291bGQg
YmUgbW9yZSBhcHByb3ByaWF0ZS4KLS0gTWF5YmUgSSBzaG91bGQgdXNlIHR5cGUgY2xhc3Nlcywg
YnV0IEkgYW0gbm90IHN1cmUgb2YgdGhlIGRpc2FkdmFudGFnZXMsIHRoZXJlIGFyZQotLSBtYW55
LiBJIHdpbGwgZXhwZXJpbWVudCBzb29uLgotLQotLSAzLgotLSBBdCBsZWFzdCBhbiBvcGVyYXRp
b24gbGlrZSAibW9kaWZ5TVZhciIgc2hvdWxkIGV4aXN0IGluIFZhcidzLgotLQotLSA0LgotLSBW
YXIgYSA9IElucHV0IGEgKyBPdXRwdXQgYSBPUiBFTFNFIFZhciBhIGIgPSBJbnB1dCBhICsgT3V0
cHV0IGIsIHdoaWNoIGRvZXNuJ3Qgc2VlbSBhIHZhcmlhYmxlCi0tIGJ1dCBpcyBtb3JlIGZsZXhp
YmxlPyBPciBtYXliZSBWYXIgYSBBTkQgV2lyZSBhIGI/Cgptb2R1bGUgVmFyIHdoZXJlCgppbXBv
cnQgQ29uY3VycmVudAppbXBvcnQgSU9SZWYKaW1wb3J0IEdIQy5JT0Jhc2UKaW1wb3J0IElPCmlt
cG9ydCBEaXJlY3RvcnkKCmRhdGEgSW5wdXQgYSA9IElucHV0IHsgcHV0SW5wdXQgOjogYSAtPiBJ
TyAoKSB9CgpkYXRhIE91dHB1dCBhID0gT3V0cHV0IHsgcmVhZE91dHB1dCA6OiBJTyBhLAoJCSAg
ICAgICAgIHdhaXRPdXRwdXQgOjogSU8gYSwKCQkgICAgICAgICBsaXN0ZW5PdXRwdXQgOjogSU8g
W2FdIH0KCmRhdGEgVmFyIGEgPSBWYXIgeyB2YXJJbnB1dCA6OiBJbnB1dCBhLAoJCSAgIHZhck91
dHB1dCA6OiBPdXRwdXQgYSB9CgotLSBQZXJmb3JtIGFuIGFjdGlvbiB3aGVuIHRoZSBvdXRwdXQg
Y2hhbmdlcwpvbk91dHB1dCA6OiBPdXRwdXQgYSAtPiAoYSAtPiBJTyBiKSAtPiBJTyAoKQpvbk91
dHB1dCBvIG0gPSBmb3JrSU8gKCBsaXN0ZW5PdXRwdXQgbyA+Pj0gbWFwTV8gbSkgPj4gcmV0dXJu
ICgpCgotLSBVdGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIHZhcmlhYmxlcwpwdXRWYXIgOjogVmFy
IGEgLT4gYSAtPiBJTyAoKQpwdXRWYXIgPSBwdXRJbnB1dCAuIHZhcklucHV0CgpyZWFkVmFyIDo6
IFZhciBhIC0+IElPIGEKcmVhZFZhciA9IHJlYWRPdXRwdXQgLiB2YXJPdXRwdXQKCndhaXRWYXIg
OjogVmFyIGEgLT4gSU8gYQp3YWl0VmFyID0gd2FpdE91dHB1dCAuIHZhck91dHB1dAoKbGlzdGVu
VmFyIDo6IFZhciBhIC0+IElPIFthXQpsaXN0ZW5WYXIgPSBsaXN0ZW5PdXRwdXQgLiB2YXJPdXRw
dXQKCm9uVmFyIDo6IFZhciBhIC0+IChhIC0+IElPIGIpIC0+IElPICgpCm9uVmFyIHYgbSA9IG9u
T3V0cHV0ICh2YXJPdXRwdXQgdikgbQoKLS0gU29tZSBzaW1wbGUgdHJhbnNmb3JtYXRpb24KCnJt
YXBJbnB1dCA6OiAgKGIgLT4gYSkgLT4gSW5wdXQgYSAtPiBJbnB1dCBiCnJtYXBJbnB1dCBmIGkg
PSBJbnB1dCB7IHB1dElucHV0ID0gXCB4IC0+IHB1dElucHV0IGkgKGYgeCkgfQoKbWFwT3V0cHV0
IDo6IChhIC0+IGIpIC0+IE91dHB1dCBhIC0+IE91dHB1dCBiCm1hcE91dHB1dCBmIG8gPSBPdXRw
dXQgeyByZWFkT3V0cHV0ID0gcmVhZE91dHB1dCBvID4+PSByZXR1cm4gLiBmLAoJCSAgICAgICAg
IHdhaXRPdXRwdXQgPSB3YWl0T3V0cHV0IG8gPj49IHJldHVybiAuIGYsCgkJICAgICAgICAgbGlz
dGVuT3V0cHV0ID0gbGlzdGVuT3V0cHV0IG8gPj49IHJldHVybiAuIChtYXAgZikgfQoKY29lcmNl
VmFyIDo6IChiIC0+IGEpIC0+IChhIC0+IGIpIC0+IFZhciBhIC0+IFZhciBiCmNvZXJjZVZhciBm
MSBmMiB2ID0gVmFyIHsgdmFySW5wdXQgPSBybWFwSW5wdXQgZjEgKHZhcklucHV0IHYpLAoJCQkg
IHZhck91dHB1dCA9IG1hcE91dHB1dCBmMiAodmFyT3V0cHV0IHYpIH0KCmNoYWluIDo6IChhIC0+
IGIpIC0+IE91dHB1dCBhIC0+IElucHV0IGIgLT4gSU8gKCkKY2hhaW4gZiBvIGkgPSBvbk91dHB1
dCBvIChwdXRJbnB1dCBpIC4gZikKCmNoYWluSU8gOjogKGEgLT4gSU8gYikgLT4gT3V0cHV0IGEg
LT4gSW5wdXQgYiAtPiBJTyAoKQpjaGFpbklPIGYgbyBpID0gb25PdXRwdXQgbyAoXCBjIC0+IGYg
YyA+Pj0gcHV0SW5wdXQgaSkKCmNvbm5lY3RWYXIgOjogKGEgLT4gYikgLT4gKGIgLT4gYSkgLT4g
VmFyIGEgLT4gVmFyIGIgLT4gSU8gKCkKY29ubmVjdFZhciBmMSBmMiB2MSB2MiA9IGRvCiAgICBv
blZhciB2MSAocHV0VmFyIHYyIC4gZjEpCiAgICBvblZhciB2MiAocHV0VmFyIHYxIC4gZjIpCgot
LSBEbyBJIG5lZWQgdGhlc2U/CmNvbnN0T3V0cHV0IDo6IGEgLT4gT3V0cHV0IGEKY29uc3RPdXRw
dXQgeCA9IE91dHB1dCB7IHJlYWRPdXRwdXQgPSByZXR1cm4geCwKCQkgICAgICAgICB3YWl0T3V0
cHV0ID0gcmV0dXJuIHgsCgkJCSBsaXN0ZW5PdXRwdXQgPSByZXR1cm4gW3hdIH0KCmR1bW15SW5w
dXQgOjogSW5wdXQgYQpkdW1teUlucHV0ID0gSW5wdXQgeyBwdXRJbnB1dCA9IFwgXyAtPiByZXR1
cm4gKCkgfQoKLS0gRm9yIGVhY2ggdmFsdWUgb2YgdGhlIG91dHB1dCwgZXhlY3V0ZSBhIGRpZmZl
cmVudCBhY3Rpb24uCi0tIGlmIHRoZSBsaXN0IG9mIGFjdGlvbnMgZW5kcyBwcmVtYXR1cmVseSwg
anVzdCBlbmQgcHJvY2Vzc2luZy4KcHJvY2Vzc091dHB1dCA6OiBPdXRwdXQgYSAtPiBbYSAtPiBJ
TyBiXSAtPiBJTyAoKQpwcm9jZXNzT3V0cHV0IG8gYSA9IGRvCgkJICAgIGwgPC0gbGlzdGVuT3V0
cHV0IG8KCQkgICAgbWFwTV8gKFwgKGEsYikgLT4gYSBiKSAoemlwIGEgbCkKCi0tIEZvciBlYWNo
IHZhbHVlIG9mIHRoZSBvdXRwdXQsIGV4ZWN1dGUgYSBkaWZmZXJlbnQgYWN0aW9uCi0tIHdoaWNo
IGRvZXMgTk9UIGRlcGVuZCBvbiB0aGUgdmFsdWUgb2YgdGhlIG91dHB1dC4KLS0gSnVzdCBhbiBl
YXNpZXIgdG8gd3JpdGUgdmFyaWFudCBvZiBwcm9jZXNzT3V0cHV0LgotLSBlZzogCi0tIHByb2Nl
c3NPdXRwdXRfIChidXR0b25DbGljayBiKSBbcHJpbnQgIkhpIixwcmludCAiYWxsIl0KLS0KLS0g
aW5zdGVhZCBvZjoKLS0gcHJvY2Vzc091dHB1dCAoYnV0dG9uQ2xpY2sgYikgW1wgKCkgLT4gcHJp
bnQgIkhpIiwKLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwgKCkgLT4gcHJpbnQg
ImFsbCJdCnByb2Nlc3NPdXRwdXRfIDo6IE91dHB1dCBhIC0+IFtJTyBiXSAtPiBJTyAoKQpwcm9j
ZXNzT3V0cHV0XyBvIGEgPSBkbwoJCSAgICAgbCA8LSBsaXN0ZW5PdXRwdXQgbwoJCSAgICAgc2Vx
dWVuY2VfIChtYXAgZnN0ICh6aXAgYSBsKSkKCi0tIFV0aWxpdHkgZnVuY3Rpb25zCQkKcGFpcklP
IDo6IElPIGEgLT4gSU8gYiAtPiBJTyAoYSxiKQpwYWlySU8gYTEgYTIgPSAKICAgIGRvICByMSA8
LSB1bnNhZmVJbnRlcmxlYXZlSU8gYTEKCXIyIDwtIHVuc2FmZUludGVybGVhdmVJTyBhMgoJcmV0
dXJuIChyMSxyMikKCSAgICAgCnppcElPIDo6IElPIFthXSAtPiBJTyBbYl0gLT4gSU8gWyhhLGIp
XQp6aXBJTyBhMSBhMiA9IAogICAgZG8gcjEgPC0gdW5zYWZlSW50ZXJsZWF2ZUlPIGExCiAgICAg
ICByMiA8LSB1bnNhZmVJbnRlcmxlYXZlSU8gYTIKICAgICAgIHJldHVybiAoemlwIHIxIHIyKQoK
LS0gVGhlIHppcCBmdW5jdGlvbnMgb24gaW5wdXRzIGFuZCBvdXRwdXRzCnppcE91dHB1dCA6OiBP
dXRwdXQgYSAtPiBPdXRwdXQgYiAtPiBPdXRwdXQgKGEsYikKemlwT3V0cHV0IG8xIG8yID0gT3V0
cHV0IHsgcmVhZE91dHB1dCA9IGRvIHIxIDwtIHJlYWRPdXRwdXQgbzEgCgkJCSAgICAgICAgICAg
ICAgICAgICByMiA8LSByZWFkT3V0cHV0IG8yCgkJCSAgICAgICAgICAgICAgICAgICByZXR1cm4g
KHIxLHIyKSwKCQkJICAgd2FpdE91dHB1dCA9IHBhaXJJTyAod2FpdE91dHB1dCBvMSkgKHdhaXRP
dXRwdXQgbzIpLAoJCQkgICBsaXN0ZW5PdXRwdXQgPSB6aXBJTyAobGlzdGVuT3V0cHV0IG8xKSAo
bGlzdGVuT3V0cHV0IG8yKSB9Cgp6aXBJbnB1dCA6OiBJbnB1dCBhIC0+IElucHV0IGIgLT4gSW5w
dXQgKGEsYikKemlwSW5wdXQgaTEgaTIgPSBJbnB1dCB7IHB1dElucHV0ID0gXCAoeCx5KSAtPiBw
dXRJbnB1dCBpMSB4ID4+IHB1dElucHV0IGkyIHkgfQoKLS0gVGhlIG1lcmdlIGZ1bmN0aW9uLCBx
dWljayAmIGRpcnR5Ci0tIHRvZG86IHJldGhpbmsgdGhlIGxpYnJhcnkgdG8gYWxsb3cgCi0tIG1l
cmdlT3V0cHV0IDo6IE91dHB1dCBhIC0+IE91dHB1dCBhIC0+IE91dHB1dCBhIC0tIGd1ZXNzIGl0
J3MgcmVhbGx5IGltcG9ydGFudC4KbWVyZ2VPdXRwdXQgOjogT3V0cHV0IGEgLT4gT3V0cHV0IGEg
LT4gSU8gKE91dHB1dCBhKQptZXJnZU91dHB1dCBvMSBvMiA9IGRvCgkJICAgIHIxIDwtIHJlYWRP
dXRwdXQgbzEKCQkgICAgdiA8LSBzdGF0ZVZhciByMQoJCSAgICBvbk91dHB1dCBvMSAocHV0VmFy
IHYpCgkJICAgIG9uT3V0cHV0IG8yIChwdXRWYXIgdikKCQkgICAgcmV0dXJuICh2YXJPdXRwdXQg
dikKCm5tZXJnZU91dHB1dCA6OiBbT3V0cHV0IGFdIC0+IElPIChPdXRwdXQgYSkKbm1lcmdlT3V0
cHV0IFthLGJdID0gbWVyZ2VPdXRwdXQgYSBiCm5tZXJnZU91dHB1dCAoeDp4cykgPSBubWVyZ2VP
dXRwdXQgeHMgPj49IG1lcmdlT3V0cHV0IHgKCgotLSBmb2xkIGFuZCBzY2FuIGZhbWlsaWVzIG5l
ZWQgZGVmaW5pdGlvbnMKCi0tIEV4ZWN1dGVzIGFuIGFjdGlvbiBlYWNoIG4gbWljcm9zZWNvbmRz
LCBnaXZpbmcgKCkgZWFjaCB0aW1lIHRoZQotLSByZXN1bHQgZGlmZmVycyBmcm9tIHRoZSBwcmV2
aW91cyBvbmUuCi0tIFRoaXMgaXMgYW4gZXhhbXBsZSB3aGVyZSB0aGVyZSdzIG5vIG5vdGlvbiBv
ZiBjdXJyZW50IHN0YXRlIGF0IHRoZQotLSBiZWdpbm5pbmcgb2YgdGhlIGNvbXB1dGF0aW9uLCBh
bmQgaXQncyB3cm9uZ2x5IGltcGxlbWVudGVkIHJpZ2h0IG5vdy4KbW9uaXRvciA6OiBFcSBhID0+
IEludCAtPiBJTyBhIC0+IElPIChPdXRwdXQgKCkpCm1vbml0b3IgbWljcm9zZWNzIGFjdCA9CiAg
ICBkbyB2IDwtIGFjdCA+Pj0gc3RhdGVWYXIKICAgICAgIHIgPC0gc3RhdGVWYXIgKCkgLS0gdGhp
cyBpcyBhcmJpdHJhcnksIHRoZSByZWFkIG9wZXJhdGlvbiBzaG91bGRuJ3QgYmUgZGVmaW5lZCEK
ICAgICAgIGZvcmtJTyAoKHNlcXVlbmNlXyAuIHJlcGVhdCkKCSAgICAgICAoZG8gCgkJbmV3IDwt
IGFjdAoJCW9sZCA8LSByZWFkVmFyIHYJCSAgICAgICAgCgkJaWYgb2xkIC89IG5ldyB0aGVuIHB1
dFZhciB2IG5ldyA+PiBwdXRWYXIgciAoKSBlbHNlIHJldHVybiAoKQoJCXRocmVhZERlbGF5IG1p
Y3Jvc2VjcykpCiAgICAgICByZXR1cm4gKHZhck91dHB1dCByKQoKLS0gSW4gY2FzZSB5b3Ugd2Vy
ZSB3b25kZXJpbmcgd2h5IEkgbmVlZGVkICJtb25pdG9yIiA6LSkKd2F0Y2hGaWxlIDo6IEludCAt
PiBGaWxlUGF0aCAtPiBJTyAoT3V0cHV0ICgpKQp3YXRjaEZpbGUgbWljcm9zZWNzIGZpbGUgPSBt
b25pdG9yIG1pY3Jvc2VjcyAoZ2V0TW9kaWZpY2F0aW9uVGltZSBmaWxlKQoKLS0gSnVzdCBhIHNt
YWxsIGV4cGVyaW1lbnQ7IGl0IHdvcmtzLiBJZiB0aGVyZSBpcyBhIHBvcnRhYmxlIHdheSBvZgot
LSBsb2NraW5nIGEgZmlsZSBpbiBoYXNrZWxsLCBqdXN0IHRlbGwgbWUhIEkgZW5zdXJlZCBhIHNp
bXBsZSBsb2NraW5nIGluCi0tIHRoaXMgYXBwbGljYXRpb24sIGJ1dCBpdCdzIG9idmlvdXNseSBu
b3QgZW5vdWdoLgpta1BlcnNpc3RlbnQgOjogKFJlYWQgYSxTaG93IGEpID0+IEludCAtPiBGaWxl
UGF0aCAtPiBWYXIgYSAtPiBJTyAoKQpta1BlcnNpc3RlbnQgbWljcm9zZWNzIGZpbGUgdmFyID0g
CiAgICBkbyBoZCA8LSByZWFkVmFyIHZhcgogICAgICAgbXV0ZXggPC0gbmV3TVZhciAoKQogICAg
ICAgdyA8LSB3YXRjaEZpbGUgbWljcm9zZWNzIGZpbGUKICAgICAgIHdydCBoZAogICAgICAgb25W
YXIgdmFyIChcIHggLT4gd2l0aE1WYXIgbXV0ZXggKFwgKCkgLT4gd3J0IHgpKQogICAgICAgb25P
dXRwdXQgdyAoXCAoKSAtPiB3aXRoTVZhciBtdXRleCAoXCAoKSAtPiByZCB2YXIpKQogICAgd2hl
cmUKICAgICAgIHdydCA9IFwgdiAtPiBkbyBoIDwtIG9wZW5GaWxlIGZpbGUgV3JpdGVNb2RlCgkJ
ICAgICAgIGhQdXRTdHIgaCAoc2hvdyB2KQoJCSAgICAgICBoQ2xvc2UgaAogICAgICAgcmQgPSBc
IHYgLT4gZG8gaCA8LSBvcGVuRmlsZSBmaWxlIFJlYWRNb2RlCgkJICAgICAgbCA8LSBoR2V0Q29u
dGVudHMgaAoJCSAgICAgIHB1dFZhciB2IChyZWFkIGwpCgoKLS0gQSBwb3NzaWJsZSBpbXBsZW1l
bnRhdGlvbiBvZiBhIHRocmVhZCBzYWZlIHN0YXRlIHZhcmlhYmxlOiBzdGF0ZVZhcgotLQotLSBU
aGUgaW1wbGVtZW50YXRpb24gc3Vja3MsIGJ1dCBpdCB3b3JrcyBhbmQgaXQncyBpbXBsZW1lbnRl
ZCB1c2luZwotLSBtdmFycyBhbmQgY2hhbm5lbHMgKHNvIEkgY2FuIHRydXN0IGl0KS4gTGF5b3V0
IGlzIGhhcmQ7IGJ1eSBhIHdpZGUtc2NyZWVuIG1vbml0b3IgOykKc3RhdGVWYXIgOjogYSAtPiBJ
TyAoVmFyIGEpCnN0YXRlVmFyIHZhbHVlID0gZG8KICAgIGxvY2sgPC0gbmV3TVZhciAoKQogICAg
bGlzdGVuZXJzIDwtIG5ld0lPUmVmIFtdCiAgICB3YWl0ZXJzIDwtIG5ld0lPUmVmIFtdICAgIAog
ICAgY3VycmVudFZhbHVlIDwtIG5ld0lPUmVmIHZhbHVlCiAgICByZXR1cm4gVmFyIHsgdmFySW5w
dXQgPSBJbnB1dCB7IHB1dElucHV0ID0gXCB2IC0+IHdpdGhNVmFyIGxvY2sgJCBcIF8gLT4gCgkJ
CQkgICAgKGRvIAoJCQkJICAgICB3cml0ZUlPUmVmIGN1cnJlbnRWYWx1ZSB2IAoJCQkJICAgICBy
IDwtIHJlYWRJT1JlZiBsaXN0ZW5lcnMKCQkJCSAgICAgbWFwTV8gKGZsaXAgd3JpdGVDaGFuIHYp
IHIKCQkJCSAgICAgcyA8LSByZWFkSU9SZWYgd2FpdGVycwoJCQkJICAgICBtYXBNXyAoZmxpcCBw
dXRNVmFyIHYpIHMpIH0sCgoJCSB2YXJPdXRwdXQgPSBPdXRwdXQgeyByZWFkT3V0cHV0ID0gd2l0
aE1WYXIgbG9jayAoXF8gLT4gcmVhZElPUmVmIGN1cnJlbnRWYWx1ZSksCgkJCQkgICAgICB3YWl0
T3V0cHV0ID0gKHdpdGhNVmFyIGxvY2sgKFxfIC0+IGRvIAoJCQkJCQkJCSAgIHYgPC0gbmV3RW1w
dHlNVmFyCgkJCQkJCQkJICAgbW9kaWZ5SU9SZWYgd2FpdGVycyAodjopCgkJCQkJCQkJICAgcmV0
dXJuIHYpID4+PQoJCQkJICAgICAgICAgICAgICAgICAgICB0YWtlTVZhciksCgkJCQkgICAgICBs
aXN0ZW5PdXRwdXQgPSAod2l0aE1WYXIgbG9jayAkIFxfIC0+IChkbyAKCQkJCQkJCQkJICAgICBj
IDwtIG5ld0NoYW4KCQkJCQkJCQkJICAgICBtb2RpZnlJT1JlZiBsaXN0ZW5lcnMgKGM6KQoJCQkJ
CQkJCQkgICAgIHJldHVybiBjKSA+Pj0KCQkJCQkJICAgICAgZ2V0Q2hhbkNvbnRlbnRzKSB9IH0K
CgoJIAo=

--Multipart_Thu__6_Mar_2003_03:17:54_+0100_0833af00
Content-Type: application/octet-stream;
 name="Makefile"
Content-Disposition: attachment;
 filename="Makefile"
Content-Transfer-Encoding: base64

IyBDaGFuZ2UgLXBhY2thZ2UtY29uZiBpZiBhcHByb3ByaWF0ZQpHSENPUFRTPS1wYWNrYWdlLWNv
bmYgL2hvbWUvdmluY2Vuem8vcHJvZ3JhbW1pL2hhc2tlbGwvcGFja2FnZS5jb25mIC1wYWNrYWdl
IGd0azIKCmRlZmF1bHQ6IE1haW4KCiU6ICUuaHMKCWdoYyAtLW1ha2UgJChHSENPUFRTKSAkPCAt
byAkQAoKY2xlYW46CglybSAqLm8gKi5oaSAtcmYgXCMqICp+IE1haW4gLWYKCnJ1biA6IE1haW4K
CS4vTWFpbgo=

--Multipart_Thu__6_Mar_2003_03:17:54_+0100_0833af00
Content-Type: application/octet-stream;
 name="Main.hs"
Content-Disposition: attachment;
 filename="Main.hs"
Content-Transfer-Encoding: base64

LS0gaXNzdWVzOiBjaGl1ZGVyZSBhdXRvbWF0aWNhbWVudGUgaSBjYW5hbGkKLS0gcGVyIGVzZW1w
aW8gcGVyY2joIGxhIGxhYmVsIGRldmUgc3RhcmUgaW4gYXNjb2x0bz8KCmltcG9ydCBWYXIKaW1w
b3J0IEdVSQppbXBvcnQgcXVhbGlmaWVkIEd0awoKbWFpbiA9ICBkbwoJKHcsYikgPC0gbWFuYWdl
ZEJ1dHRvbiAiQnllIgoKCUFwcGxpY2F0aW9uIGEgPC0gcnVuR1VJICh3aW5kb3cgKHZCb3ggW2xh
YmVsICJIZWxsbyBXb3JsZCEiLHddKSkKCglwcm9jZXNzT3V0cHV0XyAoYnV0dG9uQ2xpY2tlZCBi
KSAKCQkJICAgW3B1dElucHV0IChidXR0b25MYWJlbCBiKSAiR29vZGJ5ZSIscHV0SW5wdXQgYSAo
KV0KCg==

--Multipart_Thu__6_Mar_2003_03:17:54_+0100_0833af00--