[Haskell-beginners] Exception/Error Handling Best Practices

Theodore Lief Gannon tanuki at gmail.com
Sun Sep 25 11:53:45 UTC 2016


I recently had to deal with a situation like this in a small web service
which acts as an on-demand scraper for other sites. It runs on Servant,
which uses ExceptT as of a few versions ago (EitherT before that), but for
the remote calls it uses Wreq, which throws HttpException values. I needed
to be able to report the details of remote errors rather than having them
become a generic unhandled exception, so I was stuck with your option 0 --
but with ExceptT rather than Either, and it turns out ExceptT is pretty
slick! Here's the resultant code:

https://github.com/tejon/Meeseeks/blob/master/src/bin/MeeseeksBox.hs#L42-L48

It's a one-route service so there's a bit of clutter in there that really
should be abstracted out and/or done better. (Let's just pretend logE
doesn't exist -- semantically, it doesn't!) But other than the bit I
documented with a comment, it's entirely straightforward; and IIRC omitting
that signature defaulted the type to IOException, which looks like what you
want anyway.

tl;dr 0.5) ExceptT.

On Sat, Sep 24, 2016 at 9:49 PM, Hillary Ryan <hillaryryan92 at gmail.com>
wrote:

> Dear Haskellers,
>
> I've been working on variants of the following code:
>
> connect_from_file :: String -> IO Connection
> connect_from_file fi = do
>   s <- BL.readFile fi
>   cred <- (decode s :: Maybe Db_cred)
>   c <- connect . reformat_cred $ cred
>   return c
>
> What this code intends to do is read a config from a file in JSON, decode
> the JSON, and then open a connection based the decoded info. This code
> doesn't compile for several reasons, but I've left it in this form because
> I believe it is the most convenient for approaching my question:
>
> How should I handle errors here?
>
> Both readFile (from Bytestring) and connect (from mysql.simple) throw
> exceptions when things don't go their way, and decode uses maybe. I see
> four ways of handling these errors:
>
> 0) *All typed errors: *I could "capture" all the exceptions in Either
> types and use an EitherIO monad or transformer to automatically abort when
> a Left value appears. Now my function looks like: String -> IO (Either
> MyErrorType Connection)
> 1) *All exceptions: *I could throw an exception if Nothing appears during
> decoding. The function looks the same: String -> IO Connection
> 2) *A mix*: I could leave the connect and readFile functions alone, but
> return IO (Nothing) if the decoding doesn't work out. Now we have: String
> -> IO (Maybe Connection)
> 3) Not 0)-2)
>
> So what is the proper way to do things?
>
> Many Thanks,
> Hillary
>
>
> PS For what it is worth, I have read:
> 0) https://www.schoolofhaskell.com/user/commercial/content/exce
> ptions-best-practices . I'd love to get feedback on how to apply this
> article to my question if it is appropriate.
> 1) https://lexi-lambda.github.io/blog/2016/06/12/four-months-with-haskell/
> . From this article and others, I get the sense that there is great
> confusion in the community as to how to handle errors correctly, and worse
> yet, that different approaches are not easily compatible.
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20160925/ce4506fa/attachment.html>


More information about the Beginners mailing list