[Haskell-cafe] Looking for a more functional way to do this

Jefferson Heard jefferson.r.heard at gmail.com
Mon Aug 4 18:04:19 EDT 2008

Working with HOpenGL and GLUT, I find myself approaching a common
problem with a common solution that I don't really like all that much,
as it reeks of procedural programming.  Basically the problem is that
of complex program state, such that when the user provides input to
the program in the form of a mouse click or a typed string or
character, the program updates its internal state to reflect this,
whether that's changing the rotation, scale, or position of a screen
element, or deciding what data to have loaded from disc.

What I often do is something that looks like this:

data ProgramState  = ProgramState {
    some_associative_data :: Map String String
  , position :: GL.Vector3 Float
  , look_at :: GL Vector3 Float
  , selectables :: Map GLuint NamedObject

render :: IORef ProgramState -> IO ()
render state = do
  st <- readIORef state

handleMouseClicks :: IORef ProgramState -> GLUT.KeyboardMouseHandler
handleMouseClicks state ... = do
  st <- readIORef state

main = do
  let st = ProgramState { Map.empty ... }
      render' = render st
      mouse' = handleMouseClicks st

  GLUT.renderCallback $= render
  GLUT.keyboardMouseCallback $= Just mouse'

and so on and so forth.   Generally there are not fewer than 5 and not
more than about 32 variables that I have to track between mouse
clicks, and there's all this boilerplate code as well.  I'm searching
for a better way to do this, and I feel sure there is one.  I'm
considering using Template Haskell or possibly SYB to generate this
code, but it also seems like I also ought to be able to declare some
kind of state monad or continuation monad that can encapsulate
ProgramState without having to declare an explicit structure for it

For one thing, I'd like to genericize this code and write something
akin to Processing for Haskell (http://www.processing.org).

More information about the Haskell-Cafe mailing list