[Haskell-beginners] More Context for Failures (Data.Aeson)

Darrin Thompson darrinth at gmail.com
Thu Feb 23 20:21:25 CET 2012

I had a problem last night where I was parsing a lot of non-trivial
and annoyingly inconsistent json. These json documents have a very bad
habit of replacing lists with single objects when a particular
document contains a singleton list, which is maddening, but I can work
around it when I know to expect it. That's just one example of the
kinds of failures due to inconsistent documents.

My parsing code looks like this:

(Data.Aeson, btw)

instance FromJSON Whatever where
 parseJSON (Object o) = do
   a <- parseSomething o
   b <- parseSomethingElse o
   c <- ...
   andManyMore <- ...
   return $ Whatever a b c ...
 parseJSON _ = fail "dude"

In my code I might have 10 sub parsers so any of them might fail. When
the parser fails I see a failure message like "expected [a] but got
Object" and no additional context. And of course if I was in a
language with a stack I could just look at the stack. (And I'd be
miserable in other ways. So I'm not exactly complaining...) These
documents are long enough that I burned a lot of time comparing Aeson
dumps looking for where I got an object instead of an array.

Wouldn't it be neato if I could do this...

instance FromJSON Whatever where
 parseJSON (Object o) = do
   a <- failureContext "branchA" $ parseSomething o
   b <- failureContext "branchB" parseSomethingElse o
   return $ Whatever a b
 parseJSON _ = fail "dude"

Now when it dies, the error message will be "branchB: expected [a] but
got Object".

This seems like a useful utility. Does it already exist and I don't
know it? Would it be easy to write? I'm a little bit out of my depth
here. I've never tried to handle exceptions in Haskell before.

Seems like it would be something like:

failureContext :: (MonadIOSomething m) => String -> m a -> m a
failureContext errorContextName = -- Catch exceptions and rewrite messages
--  or wrap the exception in something and rethrow like Erlang or Java


More information about the Beginners mailing list