Swallowing an Extensible Exception in Haskell

As of version 6.10.1 of the GHC, the Control.Exception namespace now uses extensible exceptions, the old style exceptions having been relocated to Control.OldException.

This is great news, but in some cases the new extensible exceptions are a little more fussy about how they're used than the old exceptions were, and can spit out some pretty cryptic error messages if handled improperly. For example, I found myself wanting to swallow any exceptions that occurred while trying to create a new CouchDB database. I started out with some straightforward code like this:

runCouchDB' (createDB "logs") `catch` \_ -> return ()

Here's the resulting error message:

Ambiguous type variable `e' in the constraint:
  `GHC.Exception.Exception e'
    arising from a use of `Control.Exception.Base.catch'
                 at <interactive>:1:0-71
Probable fix: add a type signature that fixes these type variable(s)

Being pretty new to Haskell, it wasn't immediately obvious to me what the problem was here, but after doing some research I realized that GHC wanted to be provided with the type of exception that I wanted to catch; the idea being that the compiler forces developers to think about what they're doing to some extent. In my case, this happens to be an ErrorCall exception instance, so I rewrote my code like this:

runCouchDB' (createDB "logs") `catch` \(_ :: ErrorCall) -> return ()

… and it compiles! If I had been doing something in my lambda function above, this type might have been inferred for me by the compiler, but I had to define it explicitly because I didn't use the result in any way. A list of exception instances is available in the documentation for Control.Exception.

Posted on October 25, 2009 from Calgary

Newest Articles