I'm using the EitherT monad transformer. Combining it with the IO monad, I'm afraid I would get an exception and it would not be caught.
Indeed the exception just passes through:
import Control.Monad.Trans
import Control.Error
import System.Directory
main = runEitherT testEx >>= print
testEx :: EitherT String IO ()
testEx = lift $ removeFile "non existing filename"
But the EitherT
otherwise fits the bill perfectly to convey to callers the error. So I want to use that, not throw exceptions...
I looked at try
from Control.Exception:
try :: Exception e => IO a -> IO (Either e a)
It looks to be exactly what I want, it would fit in my EitherT IO stack... (probably with an added hoistEither
and maybe fmapL
and it starts looking verbose though) But a naive lift $ try
doesn't typecheck.
I'm sure this problem has been solved thousands of times, but I can't find any good link describing this exact issue. How is this supposed to be solved?
EDIT By "how is this supposed to be solved", I was interested in the idiomatic solution, what would be the standard way to handle that in haskell. From the answers so far, it seems the idiomatic way is to let the exceptions be thown and handle them higher-up. Seems like a bit counter-intuitive to have two flows of control and return paths, but it is apparently the way it's meant to be done.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…