如何像 Maybe monad 一样使用 Scotty 的 ActionT monad,并为错误返回早期的 http 响应?

How to use Scotty's ActionT monad like a Maybe monad, with an early http response returned for errors?

我希望能够 return 向用户自定义错误页面和状态,并在发生此类错误时在 ActionT monad 中结束计算。我的理解是,这有点像 Maybe monad,当遇到第一个 Nothing 时计算结束,但会发出最终错误消息(通过 HTTP 发送给用户)。

我的代码片段如下所示:

  liftIO $ scotty (config & port & fromEnum) $
    get "/cow/:mark" $ do
      qParams :: DM.Map LTxt.Text LTxt.Text <- DM.fromList <$> params
      markTxt <- param "mark"
      let intervalTxtMay = DM.lookup "interval" qParams
      let cowMarkMaybe = TR.readMaybe $ Txt.unpack markTxt
      cowMark <- case cowMarkMaybe of
        Nothing -> do
          status status404
          textLazy $ "Couldn't parse cow mark " ++  markTxt ++ " as integer."
          finish
        Just cmVal-> pure $ CowMark cmVal
      liftIO $ logLogIt Debug lgr ["***** Made it past cowMark ******"]
      ...

代码至少有两个问题:finish 在这里似乎没有做任何特别有用的事情,即计算继续,我仍然在我的日志中看到消息 ***** Made it past cowMark ******加载一个通常会触发 404 的页面。 第二个问题是 404 错误没有发生,我得到了 200 响应,即使它应该是 404。

有没有办法在 Scotty 中实现所需的行为?

这两个问题都源于 Nothing 案例从未被输入,因为 TR.readMaybe 总是成功。打印 markTxtcowMarkMaybe 后者应该是 Nothing.