Saturday, March 8, 2014

In Search of Maybe in C# - Part III

Following up on the last two posts[1, 2] this final post in my little series on Maybe/Option gives a third implementation of Option. This time around I'll drop the idea of letting Option implement IEnumerable and instead focus on implementing the function needed to make my Option a monad (which it wasn't actually in the last post).

First off let's reiterate the basic implementation of Option - a simple class that can be in two states 'Some' or 'None', where Options in 'Some' state contain a value and Option in 'None' state don't.

I also want to maintain the matching functionality that I had  in the other posts, so I'm keeping this:

While even this is somewhat useful as is, it becomes better if we add the remaining part of the monad; the FlatMap function (the unit function is the Some(T value) method, so only FlatMap aka Bind aka SelectMany is missing). So we add this to the OptionHelpers class:

This is nice because now we are once again able to chain operations without having to worry much about null ref exceptions.
Just for convenience I'll throw in a Filter function in the OptionHelpers as well:

To exemplify how Option can flow through a series of operations take a look at the following where there is a value,so the some case will flow through:

In the case of no value the none case will flow through as in this example:

Towards the end of the first post in the series I mentioned that it's nice to be able to treat Option as a collection. That led to Option implementing IEnumerable in the second post, thus enabling passing Options into existing code working on IEnumerables, which is quite useful when introducing Option into an existing code base. Especially so, if it's a code base that uses LINQ a lot. In such code you're likely to find functions accepting an IEnumerable and returning an IEnumerable. An Option type implementing IEnumerable fits rigth in. On the other hand, if you don't have exiting LINQ based code to fit into, the Option version in this post is maybe a bit simpler to work with because it has smaller API surface and it still provides the benefit of allowing chaining.