excToStr
为什么在这种情况下我的异常处理程序没有捕捉到模式匹配失败?
我有一个在Scotty Web 框架控制下的传入 POST 请求的处理程序:
...
import qualified Web.Scotty as W
...
W.post "/some/endpoint" $ excToStr "Cannot handle it!" $ do
b <- W.body
-- throwString "aaa" <--- THIS IS HANDLED FINE!
Just x::Maybe SomeMyType <- pure (decode b) -- BUT NOT THIS PATTERN-MATCHING FAILURE!
liftIO $ print $ show x
W.text "OK"
我的在哪里excToStr
,它看起来像:
...
import qualified Data.Text.Lazy as LT
...
excH :: (String -> String) -> ActionT LT.Text IO () -> ActionT LT.Text IO ()
excH mkErr m = catchAnyDeep m (W.text . cs . mkErr . show)
excToStr :: String -> ActionT LT.Text IO () -> ActionT LT.Text IO ()
excToStr errMsg = excH (\details -> errMsg <> " (" <> details <> ")")
catchAnyDeep
来自安全异常库。我也尝试了其他功能(catchAny
, handle
,catch
等) - 没有成功。问题的症结在于,当传入的正文无法成功解码(并decode
返回Nothing
而不是返回Just x
)时,模式匹配失败,所以我希望我的extToStr
(即excH
)会处理它,因为catchAnyDeep
(和catchAny
)处理任何异常(包括模式-匹配失败,对吧?):
catchAny :: MonadCatch m => m a -> (SomeException -> m a) -> m a
和
catchAnyDeep :: (MonadCatch m, MonadIO m, NFData a) => m a -> (SomeException -> m a) -> m a
.
如果我只抛出一个异常,throwString
那么它会按预期工作(异常被捕获)。但是模式匹配失败会导致 HTTP 内部错误 500,并显示消息“在 do 表达式中的模式匹配失败 ....”。如何处理模式匹配异常?