catch handles a selected exception raised by an IO computation and runs a handler that receives the exception. Its type is Exception e => IO a -> (e -> IO a) -> IO a, so the handler catches only the exception type it declares. section 14.4
Catch a custom exception
Define SomeFailure with an Exception instance, then write `throw (SomeFailure "Whoops") `catch` \(SomeFailure s) -> putStrLn ("Caught " ++ s)`. The handler catches SomeFailure, but not exceptions from error or undefined. section 14.4
Use catch with these boundaries in mind:
- Catch all exceptions by handling SomeException, but avoid this broad boundary when interruptions or asynchronous control flow must remain distinguishable. section 14.4
- Use catches instead of chaining several catch applications when multiple exception types share a computation, because later handlers could catch exceptions thrown by earlier handlers. section 14.4 section 14.5
- Use try when the safer result is an Either value containing either the exception or the computation result. section 14.5
ghci> :t catch
catch :: Exception e => IO a -> (e -> IO a) -> IO a
ghci> throw (SomeFailure "Whoops") `catch` \(SomeFailure s)
-> putStrLn ("Caught " ++ s)
Caught Whoops
Inspect catch's type and run a minimal SomeFailure handler interactively. section 14.4
