[Ur] Client-side programming style

Artyom Shalkhakov artyom.shalkhakov at gmail.com
Fri Jan 22 00:24:46 EST 2010


Hello,

I wanted to create a list of something with a single focus point (that
is, one of the elements of a list would be "selected"), present this
to users, and let them "edit" it (that is, manipulate the selected
element, add and remove elements, and change their selection).

I decide to create a data structure which supports these operations
(following Xmonad). In this case, it would be the zipper of a list:

> con zipper t = {L: list t, F: t, R: list t}

The elements of a list, say 1 :: 2 :: 3 with 1 being focused, would be
something like

> {L=nil, F=1, R=2::3::nil}

We can move to the "right" and to the "left", which would change the
structure like this:

> {L=1::nil, F=2, R=3::nil} (* moved to the right: this shifts one element to the left *)
> {L=2::1::nil, F=3, R=nil} (* to the right once more *)

To move one step left would be the exact opposite, so we won't cover this here.

Here's the test page in full which uses the zipper:

> fun listeditor () =
>   lst <- source (Zipper.mkzipper "foo");
>   s <- source "";
>   let
>     fun app f = s' <- get s; l' <- get lst; set lst (f s' l')
>     fun app2 f = l' <- get lst;
>       case (f l') of
>         None => return ()
>       | Some x => set lst x
>     fun showzipper (z: Zipper.zipper string): signal xbody = let
>       val lst = List.mapX (fn x => <xml><li>{[x]}</li></xml>)
>     in
>       return <xml><ul>
>         {lst (Zipper.left z)}
>         <li><b>{[Zipper.focus z]}</b></li>
>         {lst (Zipper.right z)}
>       </ul></xml>
>     end
>   in
>     return <xml><body>
>       <label>Text: <ctextbox source={s}/></label>
>       <dyn signal={l <- signal lst; showzipper l}/>
>       <button onclick={app Zipper.consLeft} value="Insert text before"/>
>       <button onclick={app Zipper.consRight} value="Insert text after"/>
>       <button onclick={app2 Zipper.moveLeft} value="Move focus up"/>
>       <button onclick={app2 Zipper.moveRight} value="Move focus down"/>
>       <button onclick={app2 Zipper.deleteLeft} value="Delete and move focus up"/>
>       <button onclick={app2 Zipper.deleteRight} value="Delete and move focus down"/>
>     </body></xml>
>   end

After looking at the example dlist module, I noticed that it was much
more elaborate. What is the reason for that? Also, I found that code
hard to follow; is there a nice metaphor or something to help making
sense out of that code?

I attached an implementation of list zipper in case anybody is interested.

Cheers,
Artyom Shalkhakov.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: zipper.ur
Type: application/octet-stream
Size: 1166 bytes
Desc: not available
URL: <http://www.impredicative.com/pipermail/ur/attachments/20100122/2be85cd8/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: zipper.urs
Type: application/octet-stream
Size: 663 bytes
Desc: not available
URL: <http://www.impredicative.com/pipermail/ur/attachments/20100122/2be85cd8/attachment-0001.obj>


More information about the Ur mailing list