开发者

Haskell Monads msum in HappStack

From

http://happstack.com/docs/crashcourse/HappstackState.html

When I run the server, the peek counter increases by

  • 1 when I peek
  • 2 when I do not peek

The relevant code in question is:

handlers :: ServerPart Response
handlers = 
    msum [ dir "peek" $ do c <- query PeekCounter
                       ok $ toResponse $ "peeked at the count and saw: " ++ show (unCounter c)
         , do c <- update (AddCounter 1)
           ok $ toResponse $ "New count is: " ++ show (unCounter c)
         ]

However, when I modify it to

handlers :: ServerPart Response
handlers = 
    msum [ dir "peek" $ do c <- query PeekCounter
                           ok $ toResponse $ "peeked at the count and saw: " +开发者_如何学C+ show (unCounter c)
         , do ok $ toResponse $ "Stop here."
         , do c <- update (AddCounter 1)
              ok $ toResponse $ "New count is: " ++ show (unCounter c)
         ]

The counter increases by

  • 0 when I peek
  • 1 when I non-peek

Is that the intended behaviour? It feels as if the second monad in msum is "leaking" even when I do a peek.


The count is being incremented an extra time because the browser requests /favicon.ico every time it loads the page. Since the last route is a catch-all, the request to /favicon.ico causes an increment.

The easiest fix is to add nullDir so that it only does an increment for /,

handlers :: ServerPart Response
handlers = 
msum [ dir "peek" $ do c <- query PeekCounter
                   ok $ toResponse $ "peeked at the count and saw: " ++ show (unCounter c)
     , do nullDir
          c <- update (AddCounter 1)
          ok $ toResponse $ "New count is: " ++ show (unCounter c)
     ]

I have updated the tutorial with that change to avoid further confusion. To confirm that it really is the /favicon.ico request that is messing things up, we could explicitly handle the request for a favicon:

handlers :: ServerPart Response
handlers = 
    msum [ dir "peek" $ do c <- query PeekCounter
                           ok $ toResponse $ "peeked at the count and saw: " ++ show (unCounter c)
         , dir "favicon.ico" $ notFound (toResponse "sorry, no favicon.ico")
         , do c <- update (AddCounter 1)
              ok $ toResponse $ "New count is: " ++ show (unCounter c)
         ]

Now we see the expected behavior.

In summary, there is nothing wrong with Happstack. The browser was making 1 or 2 requests to urls that were not /peek, and so the count got incremented once or twice. That was the intended behavior of the application. But, since people aren't expecting the /favicon.ico request it also leads to surprising behavior. So now the app has been change to only have two valid urls, /peek and /. Anything else results in a 404.

Thanks for the report!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜