Here is a definition for the GUI shown above, formulated in terms of Phooey's [http://darcs.haskell.org/packages/phooey/doc/html/Graphics-UI-Phooey-Monad.html monadic interface].

+

Here is a definition for the GUI shown above, formulated in terms of Phooey's monadic interface. See the [http://darcs.haskell.org/packages/phooey/doc/html/Graphics-UI-Phooey-Monad.html monad interface] and its [http://darcs.haskell.org/packages/phooey/doc/html/src.Graphics.UI.Phooey.Monad.hs.html source code].

<haskell>

<haskell>

Line 99:

Line 99:

Using source types allows the monadic style to capture the static nature of the input GUI while giving access to a ''source'' of dynamic values. Alternatively, we can solve the problem by replacing the [[Monad]] abstraction with one that separates static and dynamic aspects. Getting that separation is the point of the [[Arrow]] abstraction, and thus Phooey provides an arrow interface as well. Moreover, the UI arrow is implemented on top of its UI monad using a simple, reusable pattern. See the

Using source types allows the monadic style to capture the static nature of the input GUI while giving access to a ''source'' of dynamic values. Alternatively, we can solve the problem by replacing the [[Monad]] abstraction with one that separates static and dynamic aspects. Getting that separation is the point of the [[Arrow]] abstraction, and thus Phooey provides an arrow interface as well. Moreover, the UI arrow is implemented on top of its UI monad using a simple, reusable pattern. See the

Phooey is also used in GuiTV, a library for composable interfaces and "tangible values".

2 Introduction

GUIs are usually programmed in an unnatural style, in that implementation dependencies are inverted, relative to logical dependencies. This reversal results directly from the push (data-driven) orientation of most GUI libraries. While outputs depend on inputs from a user and semantic point of view, the push style imposes an implementation dependence of inputs on outputs.

A second drawback of the push style is that it is imperative rather than declarative. A GUI program describes actions to update a model and and view in reaction to user input. In contrast to the how-to-update style of an imperative program, a functional GUI program would express what-it-is of a model in terms of the inputs and of the view in terms of the model.

The questions of push-vs-pull and imperative-vs-declarative are related. While an imperative GUI program could certainly be written to pull (poll) values from input to model and model to view, thus eliminating the dependency inversion, I don't know how a declarative program could be written in the inverted-dependency style. (Do you?).

A important reason for using push rather than pull in a GUI implementation is that push is typically much more efficient. A simple pull implementation would either waste time recomputing an unchanging model and view (pegging your CPU for no benefit), or deal with the complexity of avoiding that recomputation. The push style computes only when inputs change. (Animation negates this advantage of push.)

Phooey ("Phunctional ooser ynterfaces") adopts the declarative style, in which outputs are expressed in terms of inputs. Under the hood, however, the implementation is push-based (data-driven). Phooey performs the dependency inversion invisibly, so that programmers may express GUIs simply and declaratively while still getting an efficient implementation. I have taken care to structure Phooey's implementation as simply as possible to make clear how this dependency inversion works (subject of paper in progress). In addition, Phooey supports dynamic input bounds, flexible layout, and mutually-referential widgets. (The last feature is currently broken.)

Phooey came out of Pajama and Eros. Pan is a re-implementation of the Pan language and compiler for function synthesis of interactive, continuous, infinite images. Pan and Pajama use a monadic style for specifying GUIs and are able to do so because they use the implementation trick of Compiling Embedded Languages, in which one manipulates expressions rather than values. (This trick is mostly transparent, but the illusion shows through in places.)

3 One example, three interfaces

As an example, below is a simple shopping list GUI. The

total

displayed at the bottom of the window always shows the sum of the values of the

apples

and

bananas

input sliders. When a user changes the inputs, the output updates accordingly.

Phooey presents three styles of functional GUI interfaces, structured as a monad, an arrow, and an applicative functor. Below we present code for the shopping list example in each of the three functional styles.

The examples below are all found under src/Examples/ in the phooey distribution, in the modules Monad.hs, Arrow.hs, and Monad.hs. In each case, the example is run by loading the corresponding example module into ghci and typing "

runUI ui1

".

3.1 Monad

Here is a definition for the GUI shown above, formulated in terms of Phooey's monadic interface. See the monad interface and its source code.

3.2 Arrow

Using source types allows the monadic style to capture the static nature of the input GUI while giving access to a source of dynamic values. Alternatively, we can solve the problem by replacing the Monad abstraction with one that separates static and dynamic aspects. Getting that separation is the point of the Arrow abstraction, and thus Phooey provides an arrow interface as well. Moreover, the UI arrow is implemented on top of its UI monad using a simple, reusable pattern. See the
Arrow interface doc
and its source code.

4.3 Dynamic bounds, applicative functor version

This version includes the bounds within the "val" title. I don't know how to get a "val" title on just the dynamically-bounded slider.

5 Layout

By default, UI layout follows the order of the specification, with earlier-specified components above later-specified ones. This layout may be overridden by explicit layout functions. For instance, the following definitions form variations of

ui1

laid out from bottom to top and from left to right.

GUIs & code:

uiB1 = fromBottom ui1
uiL1 = fromLeft ui1

We can also lay out a sub-assembly, as in

ui3

below

ui3 = fromBottom $
title "Shopping List"$
fromRight fruit >>= total

6 Recursive GUIs

Next is a recursive example. It is like

ui2

, but the

lo

and

hi

sliders are used to bound each other. The specification enforces the constraint that