Haskell game loop with keyboard handler











up vote
1
down vote

favorite












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









share|improve this question
























  • Did you try to use do notation? Further, look for more idiomatic ways to deal with Maybe (how about fromMaybe ?).
    – Landei
    Dec 3 '12 at 8:31















up vote
1
down vote

favorite












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









share|improve this question
























  • Did you try to use do notation? Further, look for more idiomatic ways to deal with Maybe (how about fromMaybe ?).
    – Landei
    Dec 3 '12 at 8:31













up vote
1
down vote

favorite









up vote
1
down vote

favorite











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









share|improve this question















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






haskell event-handling






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









200_success

127k15148410




127k15148410










asked Dec 2 '12 at 19:13









KAction

1333




1333












  • Did you try to use do notation? Further, look for more idiomatic ways to deal with Maybe (how about fromMaybe ?).
    – Landei
    Dec 3 '12 at 8:31


















  • Did you try to use do notation? Further, look for more idiomatic ways to deal with Maybe (how about fromMaybe ?).
    – Landei
    Dec 3 '12 at 8:31
















Did you try to use do notation? Further, look for more idiomatic ways to deal with Maybe (how about fromMaybe ?).
– Landei
Dec 3 '12 at 8:31




Did you try to use do notation? Further, look for more idiomatic ways to deal with Maybe (how about fromMaybe ?).
– Landei
Dec 3 '12 at 8:31










1 Answer
1






active

oldest

votes

















up vote
3
down vote













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





share|improve this answer























    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f19238%2fhaskell-game-loop-with-keyboard-handler%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote













    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





    share|improve this answer



























      up vote
      3
      down vote













      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





      share|improve this answer

























        up vote
        3
        down vote










        up vote
        3
        down vote









        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





        share|improve this answer














        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






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 12 '12 at 21:36

























        answered Dec 12 '12 at 20:40









        ony

        61135




        61135






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f19238%2fhaskell-game-loop-with-keyboard-handler%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Ottavio Pratesi

            Tricia Helfer

            15 giugno