
From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Paul Moore
catcher :: DBException -> DBM mark Session () catcher x = do liftIO $ putStrLn $ show x
main = do withSession (connect "..." "..." "...") ( do catchDB (do ... ) catcher )
But this doesn't catch errors in the connect call.
Wrapping the withSession in catchDB doesn't work, as withSession is in the IO monad [1], not the DBM one. But using catch with catcher doesn't work, as that expects an error handler in the IO monad, but catcher is in the DBM monad.
There's an example in the README file, in which we see: main = flip catchDB reportRethrow $ withSession (connect "sqlite_db") (do ... which basically wraps withSession with catchDB. This does catch errors in the connect call. The difference between your example and this is in the handler; your handler has type:
catcher :: DBException -> DBM mark Session ()
whereas the README example handler is from the library, and has type:
reportRethrow :: CaughtMonadIO m => DBException -> m ()
CaughtMonadIO isn't something we've bothered to explain in the docs, but this is simply a way of catching exceptions in a monad that is in the MonadIO class, which is something the standard libraries don't support. In Control.Exception, catch and friends are stuck in the IO monad. This problem has been discussed before on this list: http://www.haskell.org/pipermail/haskell/2006-February/017547.html http://www.haskell.org/pipermail/haskell/2006-April/017893.html And may well be fixed for Haskell-Prime? http://hackage.haskell.org/cgi-bin/haskell-prime/trac.cgi/ticket/110 So you just need to float your handler out one level (so it wraps withSession), and make it usable in the regular IO monad :-) That should be as simple as changing the type sig:
catcher :: CaughtMonadIO m => DBException -> m () catcher x = liftIO $ putStrLn $ show x
There are a couple of simple handlers in Database.Enumerator already, which I'd recommend you start with:
basicDBExceptionReporter :: CaughtMonadIO m => DBException -> m () basicDBExceptionReporter e = liftIO (putStrLn (formatDBException e))
reportRethrow :: CaughtMonadIO m => DBException -> m () reportRethrow e = basicDBExceptionReporter e >> IE.throwDB e
If you need something fancier then I suggest copying the code in Database.Enumerator and modifying to suit your needs.
I'm getting very confused about the relationship between the DBM stuff and the IO monad. I'm sure there are good reasons for the DBM monad, but at the moment I'm missing them, and all I'm doing is trying random things, to little avail.
The idea is to prevent resources used in database code from escaping into other, non-database, parts of your program. This lets us safely use the with- idiom to manage resources. For example, although code in the DBM monad has access to the connection object (somewhat indirectly, but it is there), it cannot return this object out of the DBM monad. When withSession closes the connection, we can be sure that further access is not possible. This is a similar technique to that used by the ST monad, I think. Oleg explains it here: http://www.haskell.org/pipermail/haskell/2006-January/017410.html Please feel free to mail me directly with questions, too, at this address or alistair@abayley.org (although my access to that maibox during working hours is sporadic and infrequent). Al Falloon wrote:
what does withSession return if there is a DBException?
Well, whatever the handler returns, same as with any other exception handler. Note that this must have the same type as whatever withSession returns, and this constraint is enforced by the type of catch/catchDB:
catchDB :: CaughtMonadIO m => m a -> (DBException -> m a) -> m a
... which is modelled on Control.Exception.catch (for regular IO monad exceptions):
catch :: IO a -> (Exception -> IO a) -> IO a
Alistair ***************************************************************** Confidentiality Note: The information contained in this message, and any attachments, may contain confidential and/or privileged material. It is intended solely for the person(s) or entity to which it is addressed. Any review, retransmission, dissemination, or taking of any action in reliance upon this information by persons or entities other than the intended recipient(s) is prohibited. If you received this in error, please contact the sender and delete the material from any computer. *****************************************************************