使用ExceptT捕获SomeException

时间:2014-10-15 15:02:40

标签: haskell exception-handling monad-transformers

我正在尝试使用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变换器堆栈的底部。我不介意丢失抛出的字符串之类的东西(糟糕的程序员!)。

2 个答案:

答案 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

相关问题