I like result types. I try to use them for (almost) any non-fatal error. This is one of the reasons I tend to prefer Jane Street standard libraries—i.e. they much prefer returning results to raising exceptions.
I’ve learned from experience—though I could have also learned it from Real World OCaml if I’d paid better attention—that having different error types in your results makes monadic binding a PITA. It is instead useful to standardize on one error type. There are generally two things you want to do with errors: report them (meaning they need to become a string at some point) or recover from them (for which packing along some information can be useful)
I see four possibilities:
- string / lazy string
- a serialization format (like
Base.Sexp.t
) - Exceptions
- Polymophic variants
pros and cons of each
string
- pros
- strings are simple
- obvious way to print
- cons
- can’t very well pack along data that can be used for recovery. This factor is sort of disqualifying from my perspective.
serialization
- pros
- most can be easily string-ified
- easy to pack along data which may be used in recovery
- cons
- sometimes the string representation is ugly—not a super fan of visually parsing s-expressions, for example.
- the shape of data isn’t obvious from the type.
- the string representation is tied to the bundled data.
exceptions
- pros
- It’s a type designed for encoding errors, and it’s pretty good both for encoding data and printing.
- cons
- pattern matching is not exhaustive.
- feels weird to pass around exceptions instead of throwing them?
polymorphic variants
- pros
- shape of the data is unambiguous.
- pattern matching is exhaustive
- cons
- less obvious how to stringify than other types.
- types can get ugly.
For some reason my “heart” is kind of drawn towards serialization formats for this purpose, but I don’t have a good reason. I think objectively speaking, exceptions make the most sense.
However, what I really would like most is for the OCaml community to standardize on one type for errors, and if there were a consensus, I would be happy to use it. I still use Jane Street’s Error.t (based on Sexp) when I’m using Base or Core, just because it integrates well with everything else.
Anyone else have thoughts or insights into this quandary?