Currying isn't just a mathematical innovation; it's also a user interface technique.
My Angle on Current UI Techniques --------------------------------- "Forms" --- text widgets, checkboxes, radio buttons, sliders, buttons, that sort of nonsense --- allow a person to create data in a computer program, and to instruct it to take actions on their behalf. They don't really help much for direct manipulation, though, where the data is already inside the computer --- perhaps as some kind of smart object inside a computer program --- and the person wants to manipulate it somehow. That's because generally such manipulation involves simultaneous selection of at least two objects: an object to act on, and an action to take on it. The primary computer UI techniques for that so far follow, in order of increasing directness: - indirect manipulation: the person's subjective experience is that they instruct a computer program what to do with the data. For example, they might write a program in a language with instructions to manipulate various objects. - verb modes: the person selects a "tool" that interprets their later clicks. For example, in a drawing program, the person might click an "erase" icon, causing their subsequent mouse clicks and drags to erase things from their drawing. - noun modes: the UI is focused on one primary object, and there are secondary objects sitting around that the person can, say, click on. When clicked on, they perform some action on the main object. For example, you might select some text (the primary focus) and then click on a "cut" menu option (the secondary object); or in Hypercard, when you create a link, it adds a floating button to your screen (the secondary object), and when you have navigated to a card (the primary focus), clicking the button directs the link to that card. - drag-and-drop: the person drags one object (generally the noun) onto the other (generally the verb). In any of these techniques, the set of nouns may be either open or closed, as may the set of verbs. Currying With Current UI Techniques ----------------------------------- Currying extends any of these techniques, including drag-and-drop, to arbitrary numbers of objects. Hypercard's "link to this page" button is an example: there's a "make link" menu item (marred by a modal dialog box, but no matter) which creates a new verb in the UI, and that verb is a curried procedure: "make link from <some particular place> to currently viewed card." Robb Beal's experimental Mac OS X "Spring" user interface for the Web used drag-and-drop for a variety of communication actions. But to select which action to take, Spring would pop up a menu after a drag was completed, for selection of the action, because all of the objects displayed in Spring canvases were nouns, not verbs. Drag-and-Drop and REST ---------------------- Drag-and-drop maps well onto REST. A drag-and-drop UI contains only three user actions: display an object, invoke an object with no arguments (by clicking or double-clicking on it), or invoke an object with one argument (by dragging another object onto it). This is particularly important because the existing REST UIs (i.e. web browsers) are utterly impoverished in their ability to submit one resource, or an entity obtained from some resource, to some other user-selected resource; and they are utterly incompetent at managing user-created data. A REST-Backed Drag-and-Drop UI ------------------------------ I propose a spatial REST UI, which would interoperate with the existing WWW as a sort of awkward browser, but would allow new kinds of web-based applications to be built. The objects arranged on the user's canvas are either resources (identified by URL) or entities. Resources are displayed with an entity obtained by dereferencing them (e.g. HTTP GET) or, failing that, just as a URL and perhaps some link text. The user can easily collapse the display down to just the title and favicon. An HTML entity usually has links to other resources within it; clicking on these links, or dragging them onto the canvas, will add those resources to the canvas. The data in an HTML form is a separate entity from the HTML itself. Typing into the form creates a clone of that entity, which is positioned on top of the original HTML page; the form can be submitted to its ACTION URL in the usual way, or to some other URL by dragging it onto that other URL, resulting in an HTTP POST (or GET) to that other URL. Dragging one resource onto another performs an HTTP POST to the URL of the second resource of a form with one field: "dropped_url", with the value of the first resource's URL. (Perhaps it should also include a representation, particularly for private resources?) It's generally desirable for a drop-target to provide visual feedback about whether it's a suitable target for a particular dragged object; this reduces user errors. Traditionally this is done with type information, but that doesn't work that well in the world of the web; most web pages have the same MIME type, and if someone else doesn't like the MIME type you got, they may be able to content-negotiate for a different representation of the same resource. The web equivalent of WSDL or IDL is the HTML form; it specifies the set of inputs required for a "remote call" in a machine-readable form, including possible values for those selected from a finite set; it normally includes human-readable documentation about those same arguments; and it may even include machine validation rules. So it seems that the most harmonious place to put this drop-target feedback is in an HTML form. At the least, you could grey out resources whose GET representation doesn't have a form with a variable named "dropped_url". Perhaps JavaScript in the form could be given a representation for the resource and decide whether it was interested. An Example Application ---------------------- I'm looking at a web page about Tim Burton's film, "Corpse Bride". I decide that I want to bookmark it, so I drag the web page onto the URL for my bookmarking service. This form POST creates a new resource (my bookmark) and redirects me to it with a 303 See Other response, which appears on my canvas next to the bookmarking service. I add some annotation ("raw images from digital cameras with dcRAW") by typing into a form; as I begin typing, a border appears around the form, because it's just been copied into a new window positioned on top of the previous one. At this point, my computer crashes, and I reboot. When I restart my REST canvas, it looks the same as before the crash, including the un-submitted form data. I'm not sure about the spelling, so I drag the form data over to a spell-checking resource. A marching-ants arrow appears from the form data to the spell-checking resource and my annotation data is submitted to it as a form POST; after checking the spelling of all the form fields in its request, the spell-checking resource responds with a very short HTML document: "Spelling OK.", which appears next to the spell-checking resource. The arrow disappears, but the form data remains visible. I finish typing the annotation and hit "Enter". The form now submits: an arrow appears from it to the titlebar of the web page and does the marching-ants thing for a second or two. The web server sends another 303 See Other, to the same URL, which causes the canvas to refresh its view of the resource, reflecting my changes; and the form data window that's obscuring it animates over to the trashcan and disappears within. Had I submitted it by dragging it onto its original resource, it would not have disappeared from the screen. Now I want to tag my bookmark with the tags "video", "media", and "free-software". I pop open a part of the canvas containing commonly-used tags; I drag the "free-software" tag onto my bookmark. This results in an HTTP POST to the bookmark resource, which fetches the "free-software" tag's URL, recognizes it as a tag to be applied, and responds by modifying the bookmark and sending another 303 to the bookmark, which again refreshes my display. Now, I always apply the "media" tag to anything I tag as "video". I have separate "media" and "video" tags, so I decide to automate the combination. I have a collection of "foreach" resources on my canvas. I pop open the "foreach noun" resource and read the description and conclude that it's the right one. I click the button in its description, and it does an HTTP POST to create a new "foreach noun" collection, which (after a 303) appears next to it on my canvas. I drag it over to my "tags" area and pop it open; its description has a link to the generic "foreach noun" resource, and links to a subsidiary resource, "add to collection". I drag "add to collection" onto the canvas, and then drag "media" and "video" onto "add to collection". Each drag results in a 303 back to the collection, which refreshes and shows me its contents. I edit its description with an inline form: "media+video". Now I click the "Collapse" button on the collection's representation to collapse it back to just its favicon and title, "media+video". Now I can apply this "foreach noun" collection to any verb by dragging the verb onto it. So I drag my bookmark onto "media+video". This results in an HTTP POST to "media+video" with the URL of my bookmark. (I'm assuming this URL is secret, so knowing the URL is sufficient proof of authority to edit.) Now the "foreach noun" server does two HTTP POSTs to the bookmark, one with the URL of the "media" tag and one with the URL of the "video" tag. Since the two HTTP responses are identical, it returns one of them to my canvas, which responds by refreshing the bookmark, which now has two more tags. (I'm not sure what it should do with different responses.) (It's a little awkward that the drag direction here is backwards from the normal tag dragging direction. This is an inherent problem with this UI, I think.) I want to email my annotations to the author of the article. I drag their mailto: link out of the article onto the canvas; I click on my bookmark's edit form to extract the form data as a separate entity. I drag this entity onto the mailto: link, and it creates a new "email message" entity on my desktop next to the mailto: link, containing all the form data. I drag the form data itself to the trashcan to make it disappear (so it stops obscuring the bookmark page), edit the mail message, and hit the "send" button to send it. Other Directions, Briefly ------------------------- Other generic services that make sense with this UI, other than "spell check", "bookmark", and "foreach noun": - foreach verb - Wayback Machine - Alexa page rank for domain - Google backlinks for URL - Technorati search for URL - automated translators - add popup links to Chinese character translations - pipeline: contains a sequence of verbs; feeds the output of one to the input of the next. (Probably has options for some minimal translation, such as extracting form data or encapsulation in a form field, since most existing web services don't know what to do with an HTTP POST with content-type text/html.) - verb chain of responsibility: try dropped URL on each verb until one returns success - noun chain of responsibility: try dropped verb with each noun until it returns success for one of them - form field renaming - makeashorterlink-type services - simple concatenation of page contents Other URL schemes other than HTTP: - aim - mailto - file Other directions: - support asynchronous invalidation, so web pages can be "live" - or at least let you manually configure polling, as Opera has for years - support non-spatial layouts, such as nested hboxes and vboxes - perhaps "titlebars" should be "tabs" that are placed on any of the four sides of a representation so as to be visible Credits ------- Inspired by Naked Objects. Inspired by Spring. Inspired by Hypercard. Bookmarking scenario from del.icio.us. End users wiring together web services inspired by Marty Tenenbaum.