[Haskell-cafe] Exception handling when using STUArray

Henning Thielemann lemming at henning-thielemann.de
Mon Mar 10 07:00:06 EDT 2008

On Mon, 10 Mar 2008, Donn Cave wrote:

> On Mar 9, 2008, at 1:07 PM, Henning Thielemann wrote:
>> How precisely would you handle IndexError if it would be an exception and
>> not just an error?
> Well, to take a hypothetical example ... I have never looked into JPEG
> image decoding, but suppose that it's moderately complicated and further
> that it involves array indexing at some point, and I have written a web
> browser that needs to decode and display images.  Maybe one in ten
> thousand JPEG images will be invalid for some reason, in a way that
> leads to an index beyond the bounds of its sequence.

Ok let's examine this example. The decoding algorithm you describe is a
non-IO function:
   JFIF.decode :: ByteString -> Image

You expect that there are inputs that must be considered corrupt. You
cannot return an image for corrupt input, thus the signature must be
   JFIF.decode :: ByteString -> Maybe Image

Now there are two possibilities: Either your implementation works 
properly, then it should return Nothing for a corrupt JFIF input, or it 
works improperly and accesses non-existing array elements and fails with 
an error. If you encounter that, you must fix that error, it would not 
help to catch the error at run-time.

> Or, I can just write the JPEG decoding algorithm, and catch index errors
> at that same place, and refuse to render the image etc..  To me, this doesn't
> pose any moral problem, and the code is bound to be clearer and more
> expressive of its core intention, than if it were burdened with layer upon
> layer of Rights and Justs to defend against a problem that has no real
> solution and may never even occur.

Internally you must check the array bounds, this might indeed mean to cope 
with Lefts and Rights. However you can process this with monad combinators 
and syntax and then looks like exception handling in IO code. If you want 
it to be handled the same way as 'file not found' you can lift the 'Left' 
to an IO exception. In my opinion, IO functions should also expose their 
exceptions by types, e.g.
  openFile :: FilePath -> IOMode -> IO (Either IOError Handle)
  openFile :: FilePath -> IOMode -> ErrorT IOError IO Handle

> If the image I'm supposed to decode isn't actually there when I try to
> open the file, then I'll display the very same icon in its place.  We want
> the same thing to happen, whatever the problem with the image:  display
> the broken image icon, and go on to render the rest of the page.  Now
> if we want to be philosophical about it, all of these problems don't
> have to be with the image - maybe it's a variant JPEG type that I didn't
> know about, or even just my coding error that happened to escape
> testing.  The web browser should carry on regardless, however, so
> the implementation shouldn't be sensitive to these philosophical
> distinctions.

Indeed all the situations "file not found", "unsupported format version", 
"corrupt file content" are exceptions, you must handle them properly with 
Maybe, Either, ErrorT, or IO exceptions, but you should not invoke 
'error'. 'error' is reserved for the case when you forget to check array 
bounds and thus a corrupt file would corrupt your program if the libraries 
default check wouldn't intervene. Actually, the array library calls 
'error' for indexes out of bound, precisely because they violate the 
calling conditions for, say (!).

More information about the Haskell-Cafe mailing list