F# Pipeline Operator in C#?

I am currently reading the Real-World Functional Programming book from Manning Publications. It’s mostly an exercise in learning F#, but also to improve my C# code as well. I finally learned what the F# pipelining operator (|>) is all about, and I was so impressed I thought I would try to figure out how to bring it into C# if possible.

Introducing the F# Pipeline Operator

Here is some F# code that defines a list of integers and a pair of functions.  They are then used in a few “higher-order” functions (functions that utilize other functions as parameters or return values, according to my book).  List.filter is equivalent to the LINQ IEnumerable.Where() extension method, and List.map is equivalent to IEnumerable.Select().

let numbers = [ 1 .. 10 ]
let isOdd(n) = n % 2 = 1
let square(n) = n * n

List.filter isOdd numbers
List.map square (List.filter isOdd numbers)

The interesting part is the last line of code, where it is argued that you lose a little bit of code readability because the function that is actually executed first (List.filter) is found second in the expression statement.  Enter the F# pipelining operator:

let squared =
  numbers
  |> List.filter isOdd
  |> List.map square

Even though we’re no longer a compact, one-liner expression, I think we’ve gained some code readability.  It says to take the list numbers and perform the following manipulations in the exact order listed.  Cool stuff, if I say so myself.

“There is No Charge for Awesomeness…or Attractiveness”

(Sorry, I’ve been watching the movie Kung Fu Panda a lot with my kids lately.  Funny stuff.)  So can this awesomeness be brought over into C#?  I opened up Visual Studio and tried to see if I could figure out how to define my own operator or reuse one of the existing ones.

I realize C# is a pretty tough language to flip keywords and operators around and invent new syntax with (ok, it’s impossible), but I tried anyway.  The type of code readability issue I wanted to remedy is the same as with the F# code snippet above.  I thought it would be nice to make C# code like the following statement more readable and digestible (especially the execution order):

Convert.ToInt32(Context.Request[“requestParam”].Trim());

As I started to (unsuccessfully) beat out some pretty rough code, I ran into problems with trying to make extension methods that are operator definition overloads and errors saying “One of the parameters of a binary operator must be the containing type.”  It just wasn’t working and then I began to realize that C# already has a pipelining syntax, even if only in one small subset of the .NET API.  You can find a decent pipelining syntax with the Fluent Interface used for the LINQ extension methods.  Its power is in the fact that the functions return the object type that was passed in and acted upon, so that more functions can be chained on afterward in a composable manner.  The ability to do things like collection.Where().Select().OrderBy() is a much more declarative and functional solution to imperative for loops (and it makes it more readable and intention revealing in my opinion).  It’s a difference in describing more what you want to be accomplished rather than how it is to be accomplished (especially when the how in programming languages is more readable to a computer than it is a human).

So the good news is that you indeed can have a nice pipelining syntax in C#, especially for APIs that are designed with Fluent Interfaces like LINQ.  However, it doesn’t solve code readability issues with code snippets like the C# fragment I showed above.  For those regular, non-fluent method calls in the rest of the .NET API, you must use old-fashioned Object-Oriented Programming practices of breaking code up into meaningful, atomic units of statements and naming and encapsulating functions cohesively in order to get more readable code.

Comments

Jonas Elfström
This looks a whole lot like the Thrush Combinator.
I implemented that one in C# a while ago
Richard Beauchamp
This comment has been removed by the author.
Mike Murray
Funny you should mention the Maybe Monad, as I've been looking into Monads off and on for several months trying to figure out how I could use them in everyday code. I likely will be posting something on this in the somewhat near future.
Anonymous
Just a small hint from someone who uses something like this in productive code on a day-to-day basis:

Take your time and extend the static methods a bit. It won't hurt to build something like a maybe-monad in there.

You know - check if the input is null and return null if so.

For this you need either:
- "where U : class"
- use Equals

For the same reason I give somethink like a "DefaultValue" Funktion that checks the input for null and responses with the default-value if so, if not it will give the original value.
Mike Murray
Very intriguing! Man I wish I had thought about that. I suppose I'm still new to designing APIs that pass around Funcs.

I was able to make the following code work with the type inference (and without having to specify the types to the Then method):

var blah = "576 "
.Then(x => x.Trim())
.Then(x => Convert.ToInt32(x));

Not too bad really. A little too much C# syntax though, but I'd argue it might be more readable than what we started with, the code everyone writes. It appears my code snippet doesn't even need the second extension method.

Thanks for sharing!
Yusuf Motara
You could try this:

static class Extn {
public static U Then<T,U>(this T o, Func<T, U> f) { return f(o); }
public static U Then<T, U>(this T o, Func<T, Func<U>> fe) { return fe(o)(); }
}

… which lets you write the more-readable:

var blah = "576 "
.Then<string,string>(x => x.Trim)
.Then(Convert.ToInt32);

Unfortunately, it seems that you need to make the generic parameters explicit; C#'s type inference is nowhere near as good as F#'s.