Our Story

Ceremony

Just Married

Partial Application in C#

by - September 10, 2015

My recent post, C# Program Entirely With Static Methods, got lots of great comments. Indeed, as is often the case, the comments are in many ways a better read than the original post. However, there were several commenters who claimed that C# does not have partial application. I take issue with this. Any language that supports higher order functions, that is, functions that can take functions as arguments and can return functions, by definition, supports partial application. C# supports higher order functions, so it also supports partial application.

Let me explain.

Let’s start by looking at partial application in F#. Here’s a simple function that adds two numbers (you can type this into F# interactive):

>let add a b = a + b;;


Now we call use our ‘add’ function to add two numbers, just as we’d expect:



> add 3 4;;
val it : int = 7


But because F# supports partial application we can also do this:



> let add3 = add 3;;
> add3 4;;
val it : int = 7


We call add with a single argument and it returns a function that takes a single argument which we can then use to add three to any number.



That’s partial application. Of course, if I try this in C# it doesn’t work:



image



Red squiggly line saying “delegate Func has two parameters but is invoked with one argument.



Case proven you say: C# does not support partial application!



But wait!



Let’s look again at the F# add function. This time I’ll include the response from F# interactive:



> let add a b = a + b;;
val add : a:int -> b:int -> int


This shows us the type of the add function. The important bit is: “a:int –> b:int –> int”. This tells us that ‘add’ is a function that takes an int and returns a function that takes an int and returns an int. It is not a function with two arguments. F# is a restrictive language, it only has functions with single arguments. That is a good thing. See Mark Seemann’s post Less is More: Langauge Features for an in depth discussion of how taking features away from a language can make it better. When people say “F# supports partial application” what they really mean is that “F# functions can only have one argument.” The F# compiler understands the syntax ‘let add a b = …’ to mean “I want a function that takes a single argument and returns a function that takes another single argument.”



There’s nothing to stop us from defining our C# function with the same signature as our F# example. Then we can partially apply it in the same way:



image



There you are: partial application in C#. No problem at all.



“But!” You cry, “That’s weird and unusual C#. I don’t want to define all my functions in such a strange way.” In that case, let me introduce you to my friend Curry. It’s not a spicy dish of South Asian origin but the process of turning a function with multiple arguments into a series of higher order functions. We can define a series of overloaded Curry extension methods:



image



We can then use them to turn ‘ordinary’ C# functions with multiple arguments into higher-order functions which we can partially apply:



image



Thinking more about Mark Seemann’s blog post, it would be an interesting exercise to start to take features away from C# whilst keeping syntactic changes to a minimum. If we took away multiple function arguments, classes, interfaces, nullable types, default mutability etc, would we end up with a subset language that would be perfect for functional programming, but still familiar to C# developers? You would of course lose backward compatibility with existing C# code, so the incentive to do it isn’t that great, but it’s a fascinating thought experiment.

You May Also Like

0 comments