Haskell Monads msum в 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)
         ]

Однако, когда я изменяю его на

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)
         ]

Счетчик увеличивается на

  • 0 когда я смотрю
  • 1 когда я не заглядываю

Это предполагаемое поведение? Такое ощущение, что вторая монада в msum «протекает», даже когда я смотрю.


person Dingfeng Quek    schedule 24.05.2011    source источник


Ответы (1)


Счетчик увеличивается еще раз, потому что браузер запрашивает /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)
     ]

Я обновил учебник с этим изменением, чтобы избежать дальнейшей путаницы. Чтобы подтвердить, что это действительно запрос /favicon.ico, который все испортил, мы могли бы явно обработать запрос для значка:

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)
         ]

Теперь мы видим ожидаемое поведение.

Таким образом, в Happstack нет ничего плохого. Браузер делал 1 или 2 запроса к URL-адресам, которые не были /peek, поэтому счетчик увеличивался один или два раза. Это было предполагаемое поведение приложения. Но поскольку люди не ожидают запроса /favicon.ico, это также приводит к неожиданному поведению. Итак, теперь приложение было изменено, чтобы иметь только два действительных URL-адреса: / peek и /. Все остальное приводит к 404.

Спасибо за отчет!

person stepcut    schedule 24.05.2011