The Problem:
One pervasive challenge in defining a decode library is the fact that OCaml/Reason's type system allows for different types than what JSON allows. This can be seen in the intFromNumber and date decoders, which impose rules on top of JSON values that JSON itself doesn't define.
It becomes an even more complex issue when dealing with Reason's "variants" which have no obvious mapping to/from JSON. In the past, bs-decode has provided two solutions to this:
- the
ExpectedValidOption error, which is sort of a catch-all, but it carries no useful error information
- the
ParseError.ResultOf and Decode.Make module functors, which is a powerful but complex solution that allows extending the underlying error type
Variant decoders have gotten easier to express with alt/oneOf and the recent addition of literal decoders, but the foundational literal decoders use ExpectedValidOption which means that don't give great error messages on failure.
The Proposal:
I haven't fully thought through this, but I'm considering adding a FailedValidation('e) error constructor.
Int and Date decoding would take advantage of this (eliminating the need for ExpectedInt and ExpectedValidDate). Literal decoders could use this, eliminating the need for ExpectedValidOption, and since the error carries a polymorphic payload, it would be easy to extend, hopefully without needing to get module functors involved.
The big thing I haven't fully figured out is how error reporting would work. Since we'll be using these validations internally, I think that means the 'e type will actually be an open polymorphic variant. For functions like ParseError.toString, you'll need to tell us how to convert your extensions to a string, but hopefully not the entire variant. :> might get involved, which is too bad, but I still think this is worth trying.
If implemented, we should:
The Problem:
One pervasive challenge in defining a decode library is the fact that OCaml/Reason's type system allows for different types than what JSON allows. This can be seen in the
intFromNumberanddatedecoders, which impose rules on top of JSON values that JSON itself doesn't define.It becomes an even more complex issue when dealing with Reason's "variants" which have no obvious mapping to/from JSON. In the past,
bs-decodehas provided two solutions to this:ExpectedValidOptionerror, which is sort of a catch-all, but it carries no useful error informationParseError.ResultOfandDecode.Makemodule functors, which is a powerful but complex solution that allows extending the underlying error typeVariant decoders have gotten easier to express with
alt/oneOfand the recent addition ofliteraldecoders, but the foundationalliteraldecoders useExpectedValidOptionwhich means that don't give great error messages on failure.The Proposal:
I haven't fully thought through this, but I'm considering adding a
FailedValidation('e)error constructor.Int and Date decoding would take advantage of this (eliminating the need for
ExpectedIntandExpectedValidDate). Literal decoders could use this, eliminating the need forExpectedValidOption, and since the error carries a polymorphic payload, it would be easy to extend, hopefully without needing to get module functors involved.The big thing I haven't fully figured out is how error reporting would work. Since we'll be using these validations internally, I think that means the
'etype will actually be an open polymorphic variant. For functions likeParseError.toString, you'll need to tell us how to convert your extensions to a string, but hopefully not the entire variant.:>might get involved, which is too bad, but I still think this is worth trying.If implemented, we should:
ParseErrorvalidatefunction that is sort of like a combination ofmapandflatMapthat lets the user return their own custom validationsvalidatefor ints (and removeExpectedInt)validatefor dates (and removeExpectedValidDate)validateforliteraldecoders (and removeExpectedValidOption)ExpectedTuple(also see Deprecate tuple decoders #121)