The future of Haskell discussion

Alastair David Reid reid@cs.utah.edu
14 Sep 2001 17:16:36 -0600


> If the GUI is based on the IO monad, then it doesn't seem like there is
> a lot of advantage  to doing it in Haskell.  It seems like a better
> idea to use a more natural language for IO and make RPC/interproc calls
> to a haskell server to get stuff done.

In other words, if you use the IO monad, you're going to have the same
programming experience (only more verbose) as a C/C++/Java programmer?

I don't think that's true.

My graphics library (http://haskell.org/graphics/) uses the IO monad
for manipulating windows and the Draw monad for doing graphics but
both feel quite different from similar code I've written in C (and, I
believe, from C++ or Java code).

In the case of manipulating windows, the different feel comes from
using concurrency to "hide the event loop" and from using layers of
abstraction to hide the full power (and horror) of the X and Win32
programming models.

In the case of the Draw monad (which is identical to the
IO monad except that it carries a "device context" around as an
implicit parameter), the different feel comes from aggressive
use of continuations (actually, they're not quite continuations
but I don't have a better word for them).  For example, you might
normally write code like this:

  do
    old_color <- selectColor blue
    old_font  <- selectFont  helvetica
    write_text "Hello World"
    selectFont  old_font
    selectColor old_color

(Reselecting the old color and font at the end is recommended Win32
programming style.)

In the HGL, you instead write:

  setPicture window (withColor blue (withFont helvetica (text "Hello World")))

or, equivalently but allegedly easier to read,

  setPicture window    $
    withColor blue     $
    withFont helvetica $
    text "Hello World"

where withColor and withFont are defined like this:

  withColor :: Color -> Draw a -> Draw a
  withColor c m = do{ old <- selectColor c; a <- m; selectColor old; return a }

  withFont  :: Font  -> Draw a -> Draw a
  withFont f m = do{ old <- selectFont f; a <- m; selectFont old; return a }

and setPicture exploits the fact that an object of type "Draw a" is a
first class object which can be stored in the window state and
executed when appropriate (e.g., when the window is uniconified).


What I'm saying is that Haskell's standard abstraction facilities mean
that even in the IO monad your programming experience can
significantly better than that of a C programmer.  (Of course your
experience can also be worse if you don't or can't bring Haskell's
strengths to bear on your problem.)


-- 
Alastair Reid        reid@cs.utah.edu        http://www.cs.utah.edu/~reid/