HappStack中的Haskell Monads msum

Din*_*uek 1 monads haskell happstack

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

当我运行服务器时,偷看计数器增加了

  • 1,当我偷看
  • 2,当我不偷看

相关的相关代码是:

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)
         ]
Run Code Online (Sandbox Code Playgroud)

但是,当我修改它时

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

柜台增加了

  • 0,当我偷看
  • 1,当我不偷看

这是预期的行为吗?感觉好像msum中的第二个monad即使在我偷看的时候也在"泄漏".

ste*_*cut 6

由于浏览器每次加载页面时都会请求/favicon.ico,因此计数会增加一个额外的时间.由于最后一个路由是全能的,因此对/favicon.ico的请求会导致增量.

最简单的解决方法是添加nullDir,使其仅为/的增量,

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)
     ]
Run Code Online (Sandbox Code Playgroud)

我已经使用该更改更新了教程,以避免进一步混淆.为了确认它确实是/favicon.ico请求搞砸了,我们可以显式处理对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)
         ]
Run Code Online (Sandbox Code Playgroud)

现在我们看到了预期的行为.

总之,Happstack没有任何问题.浏览器正在向未查看的网址发出1或2个请求,因此计数增加了一次或两次.这是应用程序的预期行为.但是,由于人们不期待/favicon.ico请求,它也会导致令人惊讶的行为.所以现在应用程序已更改为只有两个有效的URL,/ peek和/.其他任何东西都会产生404.

谢谢你的报道!