Either is Both
July 26, 2018
We started our exploration of Optionals with a function that accepted an Int. If the Int was even, the function returned it. If it wasn't even the function threw an error.
The good news was that we got great information if the the function failed.
Unfortunately, any function that calls echoEvenOrThrow has to catch and handle or rethrow the error.
We found that Optionals were a great solution. We just return nil if there's an error.
We can now use Optional's map() function to chain functions like this with functions that have no idea about Optionals at all. For example, here's how we connect to halve().
This works great in our workflow but we've lost any information on what went wrong.
In this post we'll implement a Result type that combines the information on what the error was with the ability to use map() to pipe a Result instance into a function that knows nothing about Results.
A Result is an enum with two cases: success and failure (of error).
You can see that this looks a lot like our enumeration implementation of Optional but the failure case contains information on what the error is.
Let's write a version of our echo function that returns a Result.
Test it out with an even and an odd.
The results are success(2) and failure("3 is odd").
As before, we'd like to send the results into the halve() function. halve has no idea about Result.
Take some inspiration from our map() function from Opt. The success case for Result looks the same as the some case for Opt. The difference is in the failure case. As with the none case, a failure results in a failure. The additional piece is that we have to pass the error on.
Look how easy it is to use our map() and still see the error.
The results are success(1) and failure("3 is odd").
Wait - there's more fun to come.
Let's re-introduce the numberDictionary and adapt the function valueInNumberDictionary to return a Result<String>.
Looking at the signatures of the echoEvenOrFail() and valueInNumberDictionary() functions we see that we need a flatMap(). Again we can adapt the one we wrote for Opt.
Let's take it for a ride.
The results are respectively, success("two"), failure("3 is odd"), and failure("Dictionary has no key: 4").
At some point we'll return to this topic and look at Monoids and Applicatives so we can actually combine errors. But that's it for our quick series on errors, optionals, and result types.