BINDING WITH SELECTMANY?

Check out the various functions made available to LINQ by the System.Linq.Enumerable class and you might notice a particular overload of the SelectMany method:

public static IEnumerable<TResult> SelectMany<TSource, TResult>(

  this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);

SelectMany is one of the methods specified in the query expression pattern, but this is not that particular overload. In fact, this overload is not documented as being used by the de-sugaring at all. You are free to call it yourself, but the compiler won’t do it for you. The overload is interesting because it has the exact same signature as the monad Bind, assuming that your monad is called IEnumerable.

The following lines of code implement an operation that takes two Maybe<int> values and tries to add them — of course this will only work if both values are not empty:

var result1 = 5.ToMaybe( ).

  Bind<int>(v => Maybe<int>.Empty.Bind<int>(v2 => (v + v2).ToMaybe( )));

A SelectMany implementation with the Bind signature can be added easily to the MaybeHelpers class:

public static Maybe<R> SelectMany<T, R>(this Maybe<T> m, Func<T, Maybe<R>> g) {

  return m.Bind(g);

}

As a result, it is now possible to use SelectMany instead of Bind, like this:

var result2 = 5.ToMaybe( ).SelectMany<int, int>(

  v => Maybe<int>.Empty.SelectMany<int, int>(

    v2 => (v + v2).ToMaybe( )));

Console.WriteLine("Result 2: " +

  (result2.HasValue ? result2.Value.ToString( ...

Get Functional Programming in C#: Classic Programming Techniques for Modern Projects now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.