Making C# Curry

A colleague of mine told me about currying sometime ago and I’ve been intrigued by the idea ever since. After playing around a little bit with F# and coming to understand the concept better, I thought I’d take a crack at making it work in C# because it seemed like a fun technical challenge to take on.

To begin, currying is taking a function with multiple arguments like:

string Foo(string str, object obj, int num)

And transforming it so the function call be called as a chain of function where the single parameter to that function correlates to a parameter in the original function call.

Foo(str)(obj)(num)

Currying is apparently a common thing in functional programming languages, like F# is.

So I got to thinking that this is interesting, but I wanted to be able to use the concept on an arbitrary function in C#. I didn’t want to create a bunch of Func<> templates by hand either. I just wanted it to work with any method that takes multiple parameters.

Now, I’ve chosen to start with focus here and so I didn’t bother with instance methods yet. Not going to be hard to add, I just wanted as clean a path to solving the problem at hand: the transformation itself.

First, I started to think about the individual method signatures. In the case of Foo, they would be:

str = Func<String, Func<Object, Func<Int32, String>>>
obj = Func<Object, Func<Int32, String>>
num = Func<Int32, String>

I think you can see why I didn’t want to get bogged down in Func<>s 🙂

What I needed to do then, was generate these types, define a way to capture the arguments passed in by the caller, and generate a function. The class I’ve come up with thus far to do that is as follows:

public static class Curry
{
   //Makes the return types for Func<,[THIS ONE!!!]>
   private static Type[] ReturnTypes(Type returnType, 
                                     ParameterInfo[] parameterInfo)
   {
       var result = new Stack<Type>();
       result.Push(returnType);
       foreach (var param in parameterInfo.Skip(1).Reverse())
           result.Push(typeof(Func<,>).MakeGenericType(param.ParameterType, 
                            result.Peek()));

       return result.ToArray();
   }

   private static LambdaExpression Make(MethodInfo methodInfo)
   {
       var parameters = methodInfo.GetParameters();
       //Prepare the pieces for the Func<>s
       var returnTypes = ReturnTypes(methodInfo.ReturnType, parameters);
       var expressions = new ParameterExpression[parameters.Length];

       //Create the expression parameters str, obj, num 
       for (int i = 0; i < expressions.Length; i++)
           expressions[i] = Expression.Parameter(parameters[i].ParameterType, 
                                                 parameters[i].Name);

       //Create the call Program.Foo(str, obj, num)
       Expression lastOperation = Expression.Call(methodInfo, expressions);
       //Build Curried Method Call, note I'm building back from 
       //the method invocation.
       //str => obj => num => Program.Foo(str, obj, num)
       for (int i = parameters.Length - 1; i >= 0; i--)
       {
           var genericType = typeof(Func<,>)
                            .MakeGenericType(parameters[i].ParameterType, 
                                             returnTypes[i]);
           lastOperation = Expression.Lambda(genericType, 
                                             lastOperation, 
                                             expressions[i]);
       }

       return (LambdaExpression)lastOperation;
   }
}

It takes a MethodInfo object so the user can choose whatever (currently static) method they want to use. Will need to be static and public right now. So what’s happening here is Make() gets all the parameters from the MethodInfo passed in then creates the Func<>s in the way discussed above. In addition, it creates the parameter name expressions that will allow the final Lambda to capture and use the parameter values the user passes in. Note, the parameter names equal the supplied MethodInfo’s for clarity. Then finally, starting from the Method call, it builds out the curried method structure before returning a lambda.

The first way that I came up to use this with was via a dynamic method call as such.

public static dynamic Dynamic(MethodInfo methodInfo)
{
     return Make(methodInfo).Compile();
}

Where the method is defined in my Curry static class and which I was then able to consume in my main program like so.

public class Program
{
   public static string Foo(string str, object obj, int num)
   {
       return string.Concat(str, obj, num);
   } 

   static void Main(string[] args)
   {
       var methodInfo = typeof(Program).GetMethod("Foo", BindingFlags.Static | 
                                                         BindingFlags.Public);
       dynamic fn = Curry.Dynamic(methodInfo);

       //Call made in pretty much the same way.
       //Prints string[System.Object]42
       var result = fn("string")(new object())(42);
       Console.WriteLine(result);

       //Reuse parameters
       //prints Hello, Worldx1
       //prints Hello, Worldx2
       //...
       //prints Hello, Worldx10
       var partial = fn("Hello, ")("World x");
       for (int i = 1; i <= 10; i++)
           Console.WriteLine(partial(i));

       Console.ReadKey();
    }
}

Which achieved my goals, but I’m not a fan of dynamic. I’m in a strongly typed language here so I’d like to take advantage of that. The best solution I’ve come up with to achieve that goal would be to build some kind of utility that integrates into Visual Studio to build the Curried Calls I want. Building the plugin is outside the scope of this document, but, I can render the C#:

public static string CSharp(MethodInfo methodInfo, string name)
{
    var lambda = Make(methodInfo);
    var builder = new StringBuilder();
    builder.AppendFormat("public static class {0}\r\n", name);
    builder.Append("{\r\n");
    //PrettyPrint is an extension method to render the type in C#
    builder.AppendFormat("\tpublic static {0} Exec()\r\n", 
                          lambda.Type.PrettyPrint());
    builder.Append("\t{\r\n");
    //Actually, the lamda.ToString() needs to be fixed in order to deal with
    //namespaces properly but I left that out as it's not germane to the 
    //theory I'm trying to work with.
    builder.AppendFormat("\t\treturn {0};\r\n", lambda.ToString());
    builder.Append("\t}\r\n");
    builder.Append("}\r\n");

    return builder.ToString();
}

Which I put in my Curry static class and will generate a static class like this for me…

public static class FooTarget
{
   public static Func<String, Func<Object, Func<Int32, String>>> Exec()
   {
       return str => obj => num => Program.Foo(str, obj, num);
   }
}

…that I can use exactly the same way as the dynamic calls above only now with strongly typed goodness which means intellisense.

I’ve gotten the ball rolling here on what I think is a pretty good start to enable currying in C#.

You can get a demo project here.