Wensveen's Blog

March 1, 2010

Currying in C#

Filed under: Uncategorized — Tags: , — wensveen @ 4:06 pm

A few days ago, I suddenly felt like experimenting with currying in C#. For those of you that don’t know what currying is, from Wikipedia currying: “[..] currying [..] is the technique of transforming a function that takes multiple arguments [..] in such a way that it can be called as a chain of functions each with a single argument.”

A simple example:

int Add(int x, int y) { return x + y; }
add3 = Add(3);

r1 = add3(6);
r2 = add3(9);


Most functional languages like Haskell, F#, Scala, etc. support currying out of the box. In other languages that are dynamically typed, like JavaScript, currying can be implemented fairly easily, because there are no compiler checks on the number of parameters passed to a function or method, and the type of object that is returned. JavaScript also allows to treat the parameter list (arguments) in an array-like manner, which makes implementing currying a lot easier. (C# has the params keyword, but we don’t want to have to use it when we don’t want to)

After a failed experiment with the new dynamic keyword in C# 4.0, I created a set of extension functions that take a Func or an Action (for methods that return void) and one argument, and return a Func with one less argument. For example:

var add3 = new Func(Add).Curry(3);
// add3 is now a Func<int>
int r1 = add3(6);

Because the extension functions are defined to take a Func or Action, you will have to use the proper Func or Action constructor. And you need to call Curry explicitly, unlike in languages where this is supported by their syntax.

Calling Curry(arg) multiple times can get messy for methods that take a lot of arguments:

Func f = new Func(HashOfFourStrings).Curry("a one").Curry("a two").Curry("a three");

For this reason I also created a ‘strict’ Curry extension method that returns a Func that takes its arguments one at a time:

int hash;

var hashOfFour = new Func(HashOfFourStrings).Curry();
// each call yields a new curried function
hash = hashOfFour("a one")("a two")("a three")("a four");

// equivalent
var hashOfOne = new new Func(HashOfFourStrings).Curry("a one");
hash = hashOfOne("a two", "a three", "a four");
hash = hashOfOne.Curry("a two")("a three", "a four");
hash = hashOfOne.Curry("a two").Curry("a three")("a four");
// or even, but a bit silly:
hash = hashOfOne.Curry("a two").Curry("a three").Curry("a four")();
// last curry call yields a Func<int>, so requires a zero-arg invocation

There may be times when you wish to go back from a curried to a function that takes the rest of the arguments at once, so I implemented a Decurry extension method:

int hash;

var hashCurry = new Func(HashOfFourStrings).Curry();

//yields a Func<string, Func<string, int>>
var hashOfOneTwoCurry = hashCurry("a one")("a two");
int hash = hashOfOneTwoCurry("a three")("a four");

var hashOfOneTwo = hashOfOneTwoCurry.Decurry();
// Func<string, string, int>
int hash = hashOfOneTwo("a three", "a four");

As you can see, combining Curry and Decurry can give very interesting and powerful results.

So far about usage. There are fairly simple examples. Things start to get more interesting with Funcs that take Funcs as arguments, etc. But how is it implemented?

Some ideas were taken from http://social.msdn.microsoft.com/Forums/en/vcsharp2008prerelease/thread/ce9bb58d-e55d-41ab-a000-0d20779dd3c2, especially from Marcelo Guerra’s reaction. I think it is best explained by showing the implementations of some of the extension methods:

public static Func<T2, T3, T4, Tresult>
    Curry<T1, T2, T3, T4, Tresult>(this Func<T2, T3, T4, Tresult> f, T1 a1)
{
    return (a2, a3, a4) => f(a1, a2, a3, a4);
}

public static Func<T1, Func<T2, Func<T3, Func<T4, Tresult>>>>
    Curry<T1, T2, T3, T4, Tresult>(this Func<T1, T2, T3, T4, Tresult> f)
{
    return a1 => a2 => a3 => a4 => f(a1, a2, a3, a4);
}

public static Func<T1, T2, Tresult>
    Decurry<T1, T2, Tresult>(this Func<T1, Func<T2, Tresult>> f)
{
    return (a1, a2) => f(a1)(a2);
}

The topmost Curry function takes a Func with four arguments and the first argument, and returns a function, expressed in a lambda expression, that takes three arguments and return the result of applying the first argument (that was captured in this closure) and the other three arguments to the original Func.

The second Curry function does not take the first argument, but instead returns a function that takes one argument, that returns a function that takes one argument, etc. and finally applies all arguments to the original Func.

The presented Decurry function takes a curried function (that takes each argument one at a time, like hashOfOneTwoCurry, and returns a normal, multi-parameter function like hashOfOneTwo.

You can download CurryingExperiment.zip containing a Visual Studio 2010 Beta 2 solution with a class containing all the extension methods that are needed to Curry and Decurry Funcs and Actions with up to 16 arguments (which is C#’s limit for Funcs an Actions). Also contained in the solution is a sample console application that shows some of the possibilities (all rather simple).

Have fun!

Advertisements

2 Comments »

  1. This is partial function application, not currying.

    Comment by foo — August 23, 2016 @ 11:58 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: