Haskell game loop with keyboard handler This is function, that works correctly, but it seems to be too ugly.
panel argument is never used for anything but pushing into refreshGamePanel,
and it seems to be too much case statements. How can I cleanup this?

runGameLoop :: Game -&gt; Panel -&gt; Curses GameResult
runGameLoop game panel
  = if victory game then return Victory else
      refreshGamePanel game panel &gt;&gt; render &gt;&gt; getPanelWindow panel &gt;&gt;=
        flip getEvent (Just 1)
        &gt;&gt;=
        \ event' -&gt;
          case event' of
              Nothing -&gt; runGameLoop game panel
              Just event -&gt; case event of
                EventSpecialKey (KeyFunction 2) -&gt; return Restart
                EventSpecialKey (KeyFunction 10) -&gt; return Quit
                EventSpecialKey key' -&gt; case keyToDirection key' of
                  Nothing -&gt; runGameLoop game panel
                  Just dir -&gt; runGameLoop (makeMove game dir) panel
                _ -&gt; runGameLoop game panel
There is a nice language extension in GHC called ViewPatterns. Together with LambdaCase that fature allows you to shorten your code, I think. And do notation will be much more readable for imperative part.

runGameLoop game panel | victory game = return Victory
                       | otherwise = continue
    where
      anyEvent = gatPanelWindow panel &gt;&gt;= flip getEvent (Just 1)
      isRestart = (EventSpecialKey (KeyFunction 2) ==)
      isQuit = (EventSpecialKey (KeyFunction 10) ==)
      continue = do
          refreshGamePanel game panel
          render
          anyEvent &gt;&gt;= \case
              Just (isRestart -&gt; True) -&gt; return Restart
              Just (isQuit -&gt; True) -&gt; return Quit
              Just (EventSpecialKey (keyToDirection -&gt; Just dir)) -&gt;
                  runGameLoop (makeMove game dir) panel
              _ -&gt; runGameLoop game panel


Another variant is to consider using of Monad Maybe instance

runGameLoop game panel = nextStep where
    anyEvent = gatPanelWindow panel &gt;&gt;= flip getEvent (Just 1)
    nextStep = if victory game then return Victory else do
        refreshGamePanel game panel
        render
        liftM react anyEvent &gt;&gt;= \case
            Just continuation -&gt; continuation
            Nothing -&gt; runGameLoop game panel
    react event' = do
        event' &gt;&gt;= \case
            EventSpecialKey (KeyFunction 2) -&gt; return (return Restart)
            EventSpecialKey (KeyFunction 10) -&gt; return (return Quit)
            EventSpecialKey key -&gt; do
                dir &lt;- keyToDirection key
                return (runGameLoop (makeMove game dir) panel)
            _ -&gt; Nothing