使用ExceptT捕获SomeException

Rob*_*gar 1 haskell exception-handling monad-transformers

我正在尝试使用ExceptTmonad转换器来捕获函数抛出的任何异常,如下所示:

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" 
Run Code Online (Sandbox Code Playgroud)

......但异常幸福地过得很快.我究竟做错了什么?

编辑:澄清一下,目的是捕获函数抛出的任何异常,无论异常是如何抛出的.如果它有任何区别,那么真正的函数调用位于相当深的monad变换器堆栈的底部.我不介意丢失抛出的字符串之类的东西(糟糕的程序员!).

Rom*_*aka 5

首先,您捕获运行时异常.它可以通过使用monad-control(和lifted-base)或exceptions.迈克尔斯诺曼有一篇很好的文章比较两者:例外和monad变形金刚

其次,您将捕获的异常嵌入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" 
Run Code Online (Sandbox Code Playgroud)

更紧凑(但可能稍微不那么明显)的定义intercept

intercept
  :: ExceptT SomeException IO a
  -> ExceptT SomeException IO a
intercept = handle throwE
Run Code Online (Sandbox Code Playgroud)