aeson-better-errors icon indicating copy to clipboard operation
aeson-better-errors copied to clipboard

Accumulating errors

Open Profpatsch opened this issue 2 years ago • 2 comments

It would be cool if the Applicative instance of the module could accumulate errors, instead of throwing on the first one it encounters.

e.g. if I have a block

do
  a <- Json.key "foo" Json.asText
  b <- Json.key "bar" Json.asText
  pure (a, b)

and I pass {}, this could show me an error message that both "foo" and "bar" are required but missing.

I guess it might require switching from ExceptT to e.g. Validation, and then we don’t get a generic Monad instance, but maybe Selective would be enough to do most things (and there could be a specialized Json.>>= function similar to Json.<|>).

I might experiment with keeping the interface of this library but provide error accumulation e.g. as Data.Aeson.BetterErrors.Accumulate.

Profpatsch avatar Mar 17 '22 09:03 Profpatsch

I agree that this would be cool. My initial instinct is to leave all the existing stuff alone and provide this behaviour via a new newtype - I don't think it's much of a bother to wrap/unwrap, plus it's non-breaking, and there is a law that <*> = ap.

hdgarrood avatar Mar 17 '22 16:03 hdgarrood

Hi @hdgarrood 👋.

Could you explain how I can implement a parser that accumulates errors?

I suspect the answer is in the comment above but I don't understand what you're suggesting.

I'm playing on ghci with this example:

data Person = Person String String deriving (Show)
let personParser = Person <$> key "first" asString <*> key "last" asString
parse personParser "{}"

I get

Left (BadSchema [] (KeyMissing "first"))

There's no reference to the other missing key last, nothing new considering the current behavior.

It would be great to have all the accumulated errors. What's an easy workaround? Thanks

manuca avatar Aug 17 '23 17:08 manuca