Simple netwire program
Your iff function would be better expressed with &lt;|&gt; or msum. They're for making a choice, so one of them ought be used in place of iff, I'm not sure where the True/False values are feeding out into iff, but I would maybe change them to feed out something that's a Monoid type or MonadPlus instead of Bool then use the appropriate choice technique.

You named a data type which appears to be the purpose of being a state Result, was this supposed to be a Command, Instruction, NextState, or Update instead perhaps? Result seems like a confusing name to me for what I (think?) that is.

data Update = Color (Float, Float, Float) | Quit | Reset | etc | etc | whatever
type Command = (Game -&gt; Update -&gt; IO Game) -- Presuming those functions which execute changes like doColorRed return an IO monad


I think you're missing a cohesive set of data models to present your system and it's possible states for which you could write functions to alter... When working with any UI presentation, it's usually best to create a model of your system and a separate view which responds to your model.

I would change:

  case mx of
     Left ex -&gt; putStrLn $ "Inhibited: " ++ show ex -- this should never happen
     Right (GameColor c) -&gt; do
       Al.clearToColor c
       Al.flipDisplay
       loop w' session' q
     Right Quit -&gt; return ()


To:

toColor (r,g,b) = Al.Color {Al.colorR = r, Al.colorG = g, Al.colorB = b, Al.colorA = 1.0}
ProcessCommand g (Color c) = Al.clearToColor (toColor c) &gt;&gt; Al.flipDisplay &gt;&gt; (gameLoop g)
ProcessCommand g Quit = return ()


then where you do your case, make sure your Game data type (represented as g above) has those w', session', and q variables as a part of your Game data type so the gameLoop function can execute that loop given any Game

and your case can take advantage of the exception monad instead of doing a case...

fmap (processCommand g) (mx &lt;|&gt; Right $ someFunctionThatTakesMxAndCreatesACommandToPrintTheError mx)


Give some of these techniques a try and see how it cleans up for ya. After that perhaps you'll see a higher level design appear that will make the domain a little easier to model and approach.