1
\$\begingroup\$

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 -> Panel -> Curses GameResult
runGameLoop game panel
 = if victory game then return Victory else
 refreshGamePanel game panel >> render >> getPanelWindow panel >>=
 flip getEvent (Just 1)
 >>=
 \ event' ->
 case event' of
 Nothing -> runGameLoop game panel
 Just event -> case event of
 EventSpecialKey (KeyFunction 2) -> return Restart
 EventSpecialKey (KeyFunction 10) -> return Quit
 EventSpecialKey key' -> case keyToDirection key' of
 Nothing -> runGameLoop game panel
 Just dir -> runGameLoop (makeMove game dir) panel
 _ -> runGameLoop game panel
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Dec 2, 2012 at 19:13
\$\endgroup\$
1
  • \$\begingroup\$ Did you try to use do notation? Further, look for more idiomatic ways to deal with Maybe (how about fromMaybe ?). \$\endgroup\$ Commented Dec 3, 2012 at 8:31

1 Answer 1

3
\$\begingroup\$

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 >>= flip getEvent (Just 1)
 isRestart = (EventSpecialKey (KeyFunction 2) ==)
 isQuit = (EventSpecialKey (KeyFunction 10) ==)
 continue = do
 refreshGamePanel game panel
 render
 anyEvent >>= \case
 Just (isRestart -> True) -> return Restart
 Just (isQuit -> True) -> return Quit
 Just (EventSpecialKey (keyToDirection -> Just dir)) ->
 runGameLoop (makeMove game dir) panel
 _ -> runGameLoop game panel

Another variant is to consider using of Monad Maybe instance

runGameLoop game panel = nextStep where
 anyEvent = gatPanelWindow panel >>= flip getEvent (Just 1)
 nextStep = if victory game then return Victory else do
 refreshGamePanel game panel
 render
 liftM react anyEvent >>= \case
 Just continuation -> continuation
 Nothing -> runGameLoop game panel
 react event' = do
 event' >>= \case
 EventSpecialKey (KeyFunction 2) -> return (return Restart)
 EventSpecialKey (KeyFunction 10) -> return (return Quit)
 EventSpecialKey key -> do
 dir <- keyToDirection key
 return (runGameLoop (makeMove game dir) panel)
 _ -> Nothing
answered Dec 12, 2012 at 20:40
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.