Sunday, March 1, 2009

Function Curry

Curry is good spicy food and it is also a handy programming technique. You can curry a function to produce a new function that has one less parameter... that is, the arity is reduced by one. Consider the following binary function:

add x y = x + y

If you call this function with two arguments, it will evaluate to the sum of the numbers as expected. What do you think should happen when you call the function with just one argument like this:

add 1

Should this be an error or is there a meaningful way to evaluate this? It doesn't make any sense to try adding 1 to nothing so we can't do that. What if we consider the type of the result, instead of a number why not return a function? This new function should be based on the add function but somehow incorporate that argument 1 into it. Why not fix the first parameter to be 1 and the resulting function would just have a single argument... essentially we create an increment function:

increment = add 1
increment 3 -- evaluates to 4

This is how you curry a function... it's pretty straightforward with Haskell, but how could we do this in C#? Consider the following extension method:

static class FuncExtensions
{
public static Func<B, R> Curry<A, B, R>(this Func<A, B, R> f, A x)
{
return y => f(x, y);
}
}

You can apply this extension to a binary function and use resulting "curried" unary function. Now we can write the previous Haskell code in C#:

class Program
{
static void Main(string[] args)
{
Func<int, int, int> add = (x, y) => x + y;
Func<int, int> increment = add.Curry(1);

var z = increment(3); // evaluates to 4
}
}

Currying is a way to build new functions that are based on existing ones, this allows for better code reuse and supports a stratified design.

No comments:

Post a Comment