[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
--
Darrin
More information about the Beginners
mailing list