我正在尝试使用ExceptT
monad转换器来捕获函数抛出的任何异常,如下所示:
import Control.Exception
import Control.Monad.Trans.Except
badFunction :: ExceptT SomeException IO ()
badFunction = throw DivideByZero
main :: IO ()
main = do
r <- runExceptT badFunction
case r of Left _ -> putStrLn "caught error"
Right _ -> putStrLn "nope, didn't catch no error"
......但异常幸福地过得很快。我做错了什么?
编辑:澄清一下,目的是捕获函数抛出的任何异常,无论抛出异常的方式如何。如果它有任何区别,那么真正的函数调用位于相当深的monad变换器堆栈的底部。我不介意丢失抛出的字符串之类的东西(糟糕的程序员!)。
答案 0 :(得分:5)
首先,捕获运行时异常。可以使用monad-control
(和lifted-base
)或exceptions
来完成。 Michael Snoyman有一篇很好的文章比较了两者:Exceptions and monad transformers
其次,您将捕获的异常嵌入ExceptT
。
以下是完整的工作代码:
import Control.Exception.Lifted
import Control.Monad.Trans.Except
badFunction :: ExceptT SomeException IO ()
badFunction = throw DivideByZero
intercept
:: ExceptT SomeException IO a
-> ExceptT SomeException IO a
intercept a = do
r <- try a
case r of
Right x -> return x
Left e -> throwE e
main :: IO ()
main = do
r <- runExceptT $ intercept badFunction
case r of Left _ -> putStrLn "caught error"
Right _ -> putStrLn "nope, didn't catch no error"
intercept
的更紧凑(但可能稍微不那么明显)的定义是
intercept
:: ExceptT SomeException IO a
-> ExceptT SomeException IO a
intercept = handle throwE
答案 1 :(得分:1)
我相信你想要throwE
,而不是throw
。
此外,它还是ArithException
,而不是SomeException
。