I also mentioned that in C# Bind has a different name, SelectMany. It’s one of the extension methods defined for IEnumerable<T>. And as you might have guessed, IEnumerable<T> is in fact a Monad. It’s the Monad poster child for C# in fact :)

So today let’s see how we can implement SelectMany for Identity<T> and free ourselves from the lambda soup we were drowning in in the last post.

Linq takes an interesting approach to Monads, it asks us to write a method that combines Bind and ToXxxx into a single method, SelectMany. SelectMany must have the following signature:

As you can see it looks just like Bind, except it has a third parameter, a function that takes an A and a B and returns a C. It also has a different return type, an Identity<C> instead of an Identity<B>. If your amplified type implements this method, the linq syntax ‘pre-compiler’ (not really, but it’s a good way of thinking about it) can re-write ‘for x in y’ expressions in terms of select many.

Now we’ll ‘follow the types’ to work out how to write the implementation. First we know we need to return an Identity<C>. The only place we get a C from is the return value of the select function. We can change a C into an Identity<C> by using ToIdentity:

What do we pass into select? Its first parameter is an A, we can get an A from our ‘a’ parameter by invoking its ‘Value’ method. The second parameter is a B. We can get a B from our previously defined Bind method and then invoke ‘Value’ on that as well:

Is that not much nicer? With our new insight into Linq and Monads, we can stop thinking of ‘from x in y’ as a weird attempt to write SQL in C#, but instead see it for what it really is, a kind of Monadic assignment where we assign an unamplified type on the left from an amplified type on the right.

It’s a common misconception that you can only use Linq syntax with IEnumerable<T>, this is incorrect. You can use it for Whatever<T> so long as you implement SelectMany. If you want to use other bits of linq syntax (where, let, join etc) you have to implement the appropriate matching methods, but they can all be constructed from Bind, as we’ll see a little while later.

I've found Monads a difficult abstraction to think intuitively about, and until you have that intuitive understanding, it's always going to be hard to spot a situation where they are going to be useful. But with that insight, all kinds of situations appear. I've noticed that in the Haskell community, almost everything seems to end up as a Monad, and they often stack Monads to make new ones. So for the example of the community that's been playing with Monads for longest there is ample evidence that they have a wide range of applications.

But anyway, I'm not answering your question. One example would be where you repeat a control structure frequently in your code. The simple Maybe Monad shows how you can work with 'nullable' types, wrapping up all the actual null checking. The Maybe Monad also shows how they can work as a 'short-circuit', allowing you to break out of a series of operations if a certain condition appears. That's an awkward thing to code imperatively. Monads can also be used to pass on state orthogonally to the domain logic of your program, a good example of this would be a Monadic Parser. CPS style code can also be nicely wrapped with a Monad, the F# Async Monad is an excellent example of this. The list goes on.

I'm still at the foothills of understanding these functional abstractions myself, but I've found that looking at existing examples is a very good way of getting some insight. I plan to examine a number of different Monads here, starting with the Maybe Monad in the next couple of days, so hopefully that will help too.

Code Rant

Notepad, thoughts out loud, learning in public, misunderstandings, mistakes. undiluted opinions. I'm Mike Hadlow, an itinerant developer. I live (and try to work in) Brighton on the south coast of England. Please don't mistake me for an expert in anything. I love technology and programming, but make no claims to be any good at it. Much of what you read here may be poorly thought out, wrong, or just plain dangerous.