Imperative Notation
John van Groningen
johnvg@cs.kun.nl
Wed, 10 Feb 1999 11:44:32 +0100
Nick Kallen writes
>I've done very little programming with the Object IO library although I've
>done (enough) with the 0.8 library. The points I bring up in this message
>are undoubtedly ones the Clean team have considered in the past, but I stil=
l
>think they're worth a more careful examination, especially in light of the
>recent development with Arrows in the Haskell world.
>
>> Start world
>> # (_,mbListener,world) =3D openTCP_Listener 1888 world
>> (mbTCPDuplexChan, listener, world)=3D receive (fromJust
>> mbListener) world
>> (_,{sChan,rChan}) =3D fromJust mbTCPDuplexChan
>> world =3D closeChan listener world
>> (receivedData, rChan, world) =3D receive rChan world
>> (sChan, world) =3D send sChan receivedData world
>> world =3D closeChan sChan world
>> world =3D closeChan rChan world
>> =3D world
>
>I can't be the only person whom this strikes as horrible. Dare I bring up
>the topic of a "do" notation?
You can hide some state passing using infix macros or functions. I often use=
:
(>:) infixl;
(>:) f g:=3D=3Dg f;
to hide state passing of functions that return just a new state.
Then you can write:
Start world
# (_,mbListener,world) =3D openTCP_Listener 1888 world
(mbTCPDuplexChan,listener,world) =3D receive (fromJust mbListener) world
(_,{sChan,rChan}) =3D fromJust mbTCPDuplexChan
(receivedData,rChan,world) =3D world >: closeChan listener
>: receive rChan
(sChan, world) =3D send sChan receivedData world
=3D world >: closeChan sChan
>: closeChan rChan
>Now, I know the Clean argument against Monads. Multiple environments
>preclude this in principle. Why does Clean have multiple environments? For
>concurrency purposes of course. Where is *Concurrent* Clean? Anybody's gues=
s
>;)
Using multiple environment makes it easier to reason about your program. A=
function that reads from a file gets just a File and a function that=
updates a window just a Picture. Without multiple environments, both=
functions would get the whole World, and you have to look at the=
implementation of those functions to see that they just do file io or draw =
something.
Multiple environments are also necessary for some unique datastructures,=
like arrays.
>Regardless. It is a pain to read and write even the most trivial functions
>with this explicit CPS. It makes me cringe. Am I the only Clean programmer
>who has surrendered and said: "Give me do!?"
>
>Simple stuff like the above map to "do" trivially. But, how do we handle
>multiple environments? Well, has anybody looked into whether Arrows would
>suffice?
I don't know what Arrows is.
>I'm sure some nice syntactic solution to the implicit multiple environment
>passing problem could be created. Has anyone in the Clean team tried? I'm
>under the impression that you guys have said: "We have uniqueness typing,
>it's better than monads; therefore, we don't need a do notation."
We added #, instead of do, this solved many problems with state passing.
>I don't have a proposal but I think this is a worthy topic to bring out in
>the open between Clean users and the Clean people.
The best proposal I have though of so far, is to write the name of the state=
just once, only before =3D, not after =3D, and use a special character to=
indicate that the name of the state should be added after =3D as well (at=
the end). For example, using & to mark the states:
Start world
# (_,mbListener,&world) =3D openTCP_Listener 1888 =20
(mbTCPDuplexChan,listener,&world)=3D receive (fromJust mbListener)
(_,{sChan,rChan}) =3D fromJust mbTCPDuplexChan
&world =3D closeChan listener
(receivedData,rChan,&world) =3D receive rChan
(sChan,&world) =3D send sChan receivedData
&world =3D closeChan sChan
&world =3D closeChan rChan
=3D world
John van Groningen
University of Nijmegen