Error handling styles

As I’ve mentioned before I’ve been a big proponent of handling errors in the form of the normal Erlang style tuples ({:ok, val} and {:error, reason}) as well as with patterns to handle them such as via my favorite happy and others like the useful ok_jose and ok, which all kind of do the same thing in various ways.

Then there are the Haskell’y styles of error handling that you can do via the combination of quark (Combinator library), algae (Algebraic Data Types), and witchcraft (algebraic structures and functions), which are designed to be used together. These have very powerful abilities, but is also more unusual for the normal Elixir/Erlang programmer.

The same person who made those last 3 just put out another library a while back that I just ran across, it introduces a kind of ‘mixed-mode’ between Haskell-style and Erlang-style error handling, it is called exceptional. It allows you to use the erlang style error handling of tagged tuples, the erlang style of exceptions for truly exceptional handling, and it introduces a new mode that I’d not considered before, returning the ‘value’ straight as the return on success or returning an exception on failure, note that is not raising the exception but rather returning an exception. With this it adds a few other pipe-like operators for handling and working with all of these, essentially adding in an ADT-style return method that can then be ‘resolved’ (monadically) in a very simple and Erlangy way.

Now I love tagged tuples, and combined with ok_jose and happy they handle what I am quite used to very succinctly, but this new method is quite fascinating. What are others opinions on all of these styles, including the exceptional library and how it handles all the types simultaneously (which should also work quite wonderfully with happy) and I think I will take a look at it on my next small project.

From an efficiency standpoint I love that you return either the raw return value by default instead of having to decorate them all with a tagged tuple, however that does require you to case on the raw value to verify that it is what you want, or you have to use the resolver (which I am fine with), or you could put it in happy and test on it very succinctly that way too. However the size does not really matter unless you are operating over a constrained network link or so as the exceptional library references on its associated blog post of its announcement.

What other methods could work well in elixir and why too?