Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h1>When do I use which function?</h1> <p>Here's the recommendation from the Control.Exception documentation:</p> <ul> <li>If you want to do some cleanup in the event that an exception is raised, use <code>finally</code>, <code>bracket</code> or <code>onException</code>.</li> <li>To recover after an exception and do something else, the best choice is to use one of the <code>try</code> family.</li> <li>... unless you are recovering from an asynchronous exception, in which case use <code>catch</code> or <code>catchJust</code>.</li> </ul> <h1>try :: Exception e => IO a -> IO (Either e a)</h1> <p><code>try</code> takes an <code>IO</code> action to run, and returns an <code>Either</code>. If the computation succeeded, the result is given wrapped in a <code>Right</code> constructor. (Think right as opposed to wrong). If the action threw an exception <em>of the specified type</em>, it is returned in a <code>Left</code> constructor. If the exception was <em>not</em> of the appropriate type, it continues to propagate up the stack. Specifying <code>SomeException</code> as the type will catch all exceptions, which may or may not be a good idea.</p> <p>Note that if you want to catch an exception from a pure computation, you will have to use <code>evaluate</code> to force evaluation within the <code>try</code>.</p> <pre><code>main = do result &lt;- try (evaluate (5 `div` 0)) :: IO (Either SomeException Int) case result of Left ex -&gt; putStrLn $ "Caught exception: " ++ show ex Right val -&gt; putStrLn $ "The answer was: " ++ show val </code></pre> <h1>catch :: Exception e => IO a -> (e -> IO a) -> IO a</h1> <p><code>catch</code> is similar to <code>try</code>. It first tries to run the specified <code>IO</code> action, but if an exception is thrown the handler is given the exception to get an alternative answer.</p> <pre><code>main = catch (print $ 5 `div` 0) handler where handler :: SomeException -&gt; IO () handler ex = putStrLn $ "Caught exception: " ++ show ex </code></pre> <p><strong>However,</strong> there is one important difference. When using <code>catch</code> your handler cannot be interrupted by an asynchroneous exception (i.e. thrown from another thread via <code>throwTo</code>). Attempts to raise an asynchroneous exception will block until your handler has finished running.</p> <p>Note that there is a different <code>catch</code> in the Prelude, so you might want to do <code>import Prelude hiding (catch)</code>.</p> <h1>handle :: Exception e => (e -> IO a) -> IO a -> IO a</h1> <p><code>handle</code> is simply <code>catch</code> with the arguments in the reversed order. Which one to use depends on what makes your code more readable, or which one fits better if you want to use partial application. They are otherwise identical.</p> <h1>tryJust, catchJust and handleJust</h1> <p>Note that <code>try</code>, <code>catch</code> and <code>handle</code> will catch <em>all</em> exceptions of the specified/inferred type. <code>tryJust</code> and friends allow you to specify a selector function which filters out which exceptions you specifically want to handle. For example, all arithmetic errors are of type <code>ArithException</code>. If you only want to catch <code>DivideByZero</code>, you can do:</p> <pre><code>main = do result &lt;- tryJust selectDivByZero (evaluate $ 5 `div` 0) case result of Left what -&gt; putStrLn $ "Division by " ++ what Right val -&gt; putStrLn $ "The answer was: " ++ show val where selectDivByZero :: ArithException -&gt; Maybe String selectDivByZero DivideByZero = Just "zero" selectDivByZero _ = Nothing </code></pre> <hr> <h1>A note on purity</h1> <p>Note that this type of exception handling can only happen in impure code (i.e. the <code>IO</code> monad). If you need to handle errors in pure code, you should look into returning values using <code>Maybe</code> or <code>Either</code> instead (or some other algebraic datatype). This is often preferable as it's more explicit so you always know what can happen where. Monads like <code>Control.Monad.Error</code> makes this type of error handling easier to work with.</p> <hr> <p>See also:</p> <ul> <li><a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Exception.html">Control.Exception</a></li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload