Catch SomeException with ExceptT

泪湿孤枕 提交于 2019-12-11 09:48:51

问题


I'm trying to use the ExceptT monad transformer to catch any exception thrown by a function, like so:

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" 

... but the exception happily flies by. What am I doing wrong?

Edit: to clarify, the aim is to catch any exception thrown by a function, regardless of how the exception was thrown. If it makes any difference, the real function call is at the bottom of a fairly deep monad transformer stack. I don't mind missing things like thrown strings (bad programmer!).


回答1:


First, you catch your runtime exception. It can be done by using either monad-control (and lifted-base) or exceptions. Michael Snoyman has a nice article comparing the two: Exceptions and monad transformers

Second, you embed the caught exception in ExceptT.

Here's the complete working code:

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" 

A more compact (but perhaps somewhat less obvious) definition of intercept is

intercept
  :: ExceptT SomeException IO a
  -> ExceptT SomeException IO a
intercept = handle throwE



回答2:


I believe you want throwE, not throw.

Also, it'll be an ArithException, not a SomeException.



来源:https://stackoverflow.com/questions/26385809/catch-someexception-with-exceptt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!