Reputation: 16079
When I query my database, it might throw one of four different kinds of exceptions.
FormatError
QueryError
ResultError
SqlError
I want to write a function that catches any of those 4 exceptions generated by query
and lifts them into ExceptT
.
runQuery :: (ToRow q, FromRow r) => Query -> q -> ExceptT ServantErr IO [r]
runQuery conn q sub = do
res <- liftIO $ try $ Postgres.query conn q sub
case res of
Left err -> throwError (postgresErr err)
Right r -> return r
postgresErr :: ??? -> ServantErr
postgresErr e = err500 { errBody = ByteString.pack (show e) }
This doesn't work. try
isn't catching anything. How can I catch any of the 4 exception types, and map it to a ServantErr
depending on the type, but still allow any exceptions I don't handle to pass through?
Upvotes: 2
Views: 215
Reputation: 18199
GHC's Exception
class forms a hierarchy, with the SomeException
type at the top. So to catch any exception whatsoever, use that:
postgresErr :: SomeException -> ServantErr
(Ideally postgresql-simple
could have added its own intermediate catch-all exception type that you could use, but I couldn't see any.)
If you want to catch exactly those four, the best way I know is to use the catches
function:
catches :: IO a -> [Handler a] -> IO a
Unfortunately this requires you to provide one Handler
for each of them (although probably they'll only differ in their type signature).
Upvotes: 6