Grapefruit is a library for creating graphical user interfaces in a declarative way. It is currently based on Gtk2Hs but implementations on top of other GUI libraries are planned for the future.
Grapefruit makes it possible to implement graphical user interfaces by describing them as systems of interconnected components. Components can be visible components like widgets and windows but also invisible components which provide certain control functionality. Component systems can be built from components by using methods from the
Components communicate via signals and event streams. A signal denotes a time-varying value, and an event stream denotes a sequence of events occuring at discrete points in time. Several functions allow the construction of signals and event streams in a purely functional manner.
Grapefruit has also support for list signals, special signals denoting time-varying lists where each element has a unique identity. An algebra for list signals provides operations like concatenation, filtering and sorting. The key point is that when the value of a list signal changes, the values of the dependent list signals do not have to be recalculated completely but can be just updated to reflect the change.
User interfaces with a changing collection of widgets are also possible with Grapefruit. There is a special widget which takes a list signal of widgets as its input and always contains the elements of it as its child widgets.
With Grapefruit, user interface descriptions always cover the complete lifetime of the respective interface. No explicit event handler registrations and no explicit recalculations of values are necessary. This is in line with the declarative nature of Haskell because it stresses how the user interface operates instead of how this operation is achieved. Internally though, signals and event streams are implemented efficiently using the event dispatching and handling mechanism of the underlying GUI toolkit.
The roots of Grapefruit lie in systems like FranTk and wxFruit. Grapefruit tries to combine concepts of these systems with new ideas to become a system which maintains a reasonable balance between ease of use and efficiency.
As of September 2007, Grapefruit is in an early stage. The basic concepts are implemented but the implementation is still subject to notable change. Things planned for the next months cover the following:
- a new signal type for discrete signals which improves and replaces the currently used event stream type
- support for animations
- support for the model-view pattern
Furthermore, work on formal specification and verification of GUI properties based on Grapefruit’s GUI programming interface and dependent types has just started. The proof assistant Coq will be used in this context.
The source code of Grapefruit resides inside a darcs repository under http://softbase.org/grapefruit/darcs/main/. To get a copy, you can use the command
darcs get http://softbase.org/grapefruit/darcs/main.
In September 2007, Grapefruit started to use type families. Therefore, you need a recent version of GHC. Installing this and Gtk2Hs on top of it can be tricky. You might want to do the following which worked for me on Debian GNU/Linux 4.0, running on an i386 processor:
- Get and install the binary release of GHC 188.8.131.5270916.
- Copy the file
$GHC_INSTALL_DIR/lib/ghc-184.108.40.20670916. (See GHC bug #1703.)
- Get the source release of Gtk2Hs 0.9.12.
- Make the following modifications to the file
> if HAVE_SPLIT_BASE
> tools_c2hs_c2hsLocal_EXTERNALDEPS += pretty containers array
> if HAVE_SPLIT_BASE
> libHSgtk_a_EXTERNALDEPS += containers array
> if HAVE_SPLIT_BASE
> libHSsoegtk_a_EXTERNALDEPS += old-time
- Make the following modification to the file
> dnl check for a recent ghc-6.7 or later as a proxy for the base package split
> GTKHS_PROG_CHECK_VERSION($GHC_VERSION, -ge, 6.7.20070912, [
> AC_DEFINE([HAVE_SPLIT_BASE], , [Using split base package.])
> AM_CONDITIONAL(HAVE_SPLIT_BASE, test "$HAVE_SPLIT_BASE" = "yes")
- Build and install the library as usual.
There is also documentation generated by Haddock. This documentation comes in two flavors. The API documentation covers only the public interface while the complete documentation covers also the internals. Note that the documentation might be out of date since it is not automatically regenerated on every commit yet.
- Wolfgang Jeltsch: Funktionale GUI-Programmierung in Haskell mit Grapefruit. Haskell in Leipzig 2. July 10, 2007.
- presentation (in German)