Note that there are some explanatory texts on larger screens.

plurals
  1. POHow do I combine IOError exceptions with locally relevant exceptions?
    primarykey
    data
    text
    <p>I am building a Haskell application and trying to figure out how I am going to build the error handling mechanism. In the real application, I'm doing a bunch of work with Mongo. But, for this, I'm going to simplify by working with basic IO operations on a file.</p> <p>So, for this test application, I want to read in a file and verify that it contains a proper fibonnacci sequence, with each value separated by a space:</p> <pre><code>1 1 2 3 5 8 13 21 </code></pre> <p>Now, when reading the file, any number of things could actually be wrong, and I am going to call all of those <a href="http://www.haskell.org/haskellwiki/Error_vs._Exception" rel="nofollow">exceptions in the Haskell usage of the word</a>.</p> <pre><code>data FibException = FileUnreadable IOError | FormatError String String | InvalidValue Integer | Unknown String instance Error FibException where noMsg = Unknown "No error message" strMsg = Unknown </code></pre> <p>Writing a pure function that verifies the sequence and throws an error in the case that the sequence is invalid is easy (though I could probably do better):</p> <pre><code>verifySequence :: String -&gt; (Integer, Integer) -&gt; Either FibException () verifySequence "" (prev1, prev2) = return () verifySequence s (prev1, prev2) = let readInt = reads :: ReadS Integer res = readInt s in case res of [] -&gt; throwError $ FormatError s (val, rest):[] -&gt; case (prev1, prev2, val) of (0, 0, 1) -&gt; verifySequence rest (0, 1) (p1, p2, val') -&gt; (if p1 + p2 /= val' then throwError $ InvalidValue val' else verifySequence rest (p2, val)) _ -&gt; throwError $ InvalidValue val </code></pre> <p>After that, I want the function that reads the file and verifies the sequence:</p> <pre><code>type FibIOMonad = ErrorT FibException IO verifyFibFile :: FilePath -&gt; FibIOMonad () verifyFibFile path = do sequenceStr &lt;- liftIO $ readFile path case (verifySequence sequenceStr (0, 0)) of Right res -&gt; return res Left err -&gt; throwError err </code></pre> <p>This function does exactly what I want if the file is in the invalid format (it returns <code>Left (FormatError "something")</code>) or if the file has a number out of sequence (<code>Left (InvalidValue 15)</code>). But it throws an error if the file specified does not exist.</p> <p>How do I catch the IO errors that readFile may produce so that I can transform them into the FileUnreadable error?</p> <p>As a side question, is this even the best way to do it? I see the advantage that the caller of <code>verifyFibFile</code> does not have to set up two different exception handling mechanisms and can instead catch just one exception type.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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