Currying is the process of transforming a function that takes multiple arguments into a function that takes one argument, where the remaining arguments have been specified by the curry. You can find a great explanation of it at
Wes Dyer’s blog, but essentially in C# terms, when you have an anonymous delegate that takes n parameters, you can pass it to a currying method, lets call it Curry, specifying values for all the parameters bar the first one, and get back another anonymous delegate. This returned delegate will maintain the values passed to the Curry method by building a closure around them, so that when the method is eventually called, you only need to pass the single remaining parameter to it.
Wes Dyer’s explanation makes extensive use of a C# 3.0 feature called Lambda expressions. C# 3.0 features are generally just syntactic sugar around structures that are easily constructed in C# 2.0, if a little more verbosely, which is good news for anyone that can’t make the change for a while. For me, dealing with something new like currying is difficult enough without trying to deal with lambda expressions at the same time, so the examples in this post will use C# 2.0-style anonymous delegates, rather than lambdas, for the bits about currying. You’ll still need a build of Orcas (I suggest
this one) to play with the code below, but only because I used some automatic properties and list and object initializer syntax. I should also point out that the example below might not represent the best use for currying. Its fun to play with but at the moment its very much a cool hammer looking for a nail. Having said that, passing a delegate that takes multiple parameters as a predicate to a Lists Find method (which can only take a single parameter) works well as an example. With that said…
Lets say we have a list of Person objects. The Person object look like this:
class Person
{
public string Name
{
get;
set;
}
public int Age
{
get;
set;
}
public override string ToString()
{
return string.Format(“Name: {0}, Age: {1}”, Name, Age);
}
}
and the list is initialized like this:
List<Person> people = new List<Person>
{
new Person(){Name=“Andrew”, Age=27},
new Person(){Name=“Tony”, Age=32},
new Person(){Name=“Gary”, Age=23},
};
Now, if you wanted to use the Lists Find method to find all the people who were named Tony and aged 32 you could use the following code:
Console.WriteLine(people.Find(delegate(Person person) { return person.Name == “Tony” && person.Age == 32; }));
Nothing crazy so far. If you now wanted to call the Find method twice within the same method, but with different Name and Age criteria, you could assign the anonymous delegate to a variable, and declare some variables outside the scope of the delegate. By referring to them inside the delegate, the compiler will generate a closure around them, making the values available at runtime. This would look like the following:
string searchName = string.Empty;
int searchAge = 0;
Predicate<Person> findPersonPredicate =
delegate(Person person)
{
return person.Name == searchName && person.Age == searchAge;
};
searchName = “Andrew”;
searchAge = 27;
Console.WriteLine(people.Find(findPersonPredicate));
searchName = “Gary”;
searchAge = 23;
Console.WriteLine(people.Find(findPersonPredicate));
It would be cool if those temporary search variables weren’t needed, and this is where currying comes in, at least in this example. Lets say you wanted to specify those search values as parameters to a search function. We still need a delegate because we’re still going to use the Find method. The delegate, along with its type, might look like this:
private delegate bool UncurriedPredicate(Person person, string searchName, int searchAge);
UncurriedPredicate uncurriedPredicate = delegate(Person person, string searchName, int searchAge)
{
return person.Name == searchName && person.Age == searchAge;
};
Of course, this can’t be passed as a predicate because it doesn’t match the Predicate<T> signature, which only takes a single parameter. We need to transform this into an anonymous delegate that takes only one parameter, a Person object, while specifying the other parameters. If we had a Curry method, we could do this:
CurriedPredicateBuilder<Person> curriedPredicateBuilder = Curry(uncurriedPredicate);
Console.WriteLine(people.Find(curriedPredicateBuilder(“Andrew”, 27)));
CurriedPredicateBuilder is a delegate type that looks like this:
private delegate Predicate<T> CurriedPredicateBuilder<T>(string searchName, int searchAge);
That is, a function that accepts two parameters, a string and an int, and returns a Predicate<T>. This is why its called CurriedPredicateBuilder. Curry is a method that returns another method that we can use to build Predicate<T> delegates. Finally, the Curry method looks like this:
private static CurriedPredicateBuilder<Person> Curry(UncurriedPredicate uncurriedPredicate)
{
return delegate(string searchName, int searchAge)
{
return delegate(Person person)
{
return uncurriedPredicate(person, searchName, searchAge);
};
};
}
I’ve hard coded the return type to be CurriedPredicateBuilder<Person> just for the moment, to make it easier to see what’s going on. This can all be made generic, which I’ll do later on.
So what
is going on? When Curry is called, the return value is a CurriedPredicateBuilder<Person> delegate that accepts two parameters, and returns another delegate. So its really a function that builds other functions, hence the name. This inner delegate matches the Predicate<T> signature, so it can be passed to the Find method. Internally it calls the original uncurriedPredicate that was passed to Curry, the arguments for which come from the closure that the compiler will have built around the outer delegate’s arguments. Confused? Good! You should be.
The ultimate goal of all this is something called partial function application, where you can define and pass around functions that have n-1 of their parameters already specified. The two step process of currying a method and then calling the returned function to specify its first n-1 parameters can be combined into a single step using another method called Partial:
private static Predicate<Person> Partial(UncurriedPredicate uncurriedPredicate, string searchName, int searchAge)
{
return delegate(Person person)
{
return uncurriedPredicate(person, searchName, searchAge);
};
}
And with a small bit of work, this can be modified to accept and return generic types.
private static Func<A, D> Partial<A, B, C, D>(Func<A, B, C, D> f, B arg1, C arg2)
{
return delegate(A arg0)
{
return f(arg0, arg1, arg2);
};
}
We can now redefine our original uncurriedPredicate anonymous delegate to be of type
Func<
Person,
string,
int,
bool>, and pass it to the Partial method, with the search parameters:
Func<Person, string, int, bool> uncurriedPredicate = delegate(Person person, string searchName, int searchAge)
{
return person.Name == searchName && person.Age == searchAge;
};
Console.WriteLine(people.Find(new Predicate<Person>(Partial(uncurriedPredicate, “Andrew”, 27))));
Again, for anyone unfamiliar with C# 3.0, Func is a delegate type provided by the .NET framework to make it easier to work with lambda expressions. Func<A, B, C>, for example, represents a delegate that accepts two arguments, of type A and B respectively, and returns an object of type C.
Now, before I get any comments (it could happen…) about living in the past, I realize list searches are much easier to do in C# 3.0 with query expressions. All of the above can be done something like this:
var person = (from p in people
where p.Name == “Andrew” && p.Age == 27
select p).First();
but that doesn’t make the other way any less fun to play with:)