Category Archives: Concepts

F# currying in a little more depth

Unlike Scala, for example, F# does not use an alternate syntax to differentiate a “curry-able” function from a “non-curry-able” function. I was therefore interested in what the F# compiler does to when supplied with a function like the following

let add a b c = a + b + c

Does it really generate something like the following code?

let add a = 
    let add1 b = 
        let add2 c = 
            a + b + c
        add2
    add1

Obviously this wouldn’t be great as the code requires closures and sub-functions to be created and so would be less performant in situations where we do not require the currying capabilities.

Thankfully the F# compiler takes care of everything for us so that if we have code in our application which solely uses the add function, like this

let r = add 1 2 3

then the compiler simply generates the following, this is taken from ILSpy from the compiled code and obviously reproduced in C# which I think demonstrates pretty clearly what happens.

public static int add(int a, int b, int c)
{
   return a + b + c;
}

// therefore our call to the 
// function becomes
int r = Program.add(1, 2, 3);

Now, what happens if we start currying our functions, with code like this

let r = add 1 2 
let r1 = r 3

Here the compiler still creates the add method as before (as one would expect) but it also creates the following internal class (I’ve removed attributes to make it all a little cleaner)

internal sealed class r@9
{
   public int a;
   public int b;

   internal r@9(int a, int b)
      : this()
   {
      this.a = a;
      this.b = b;
   }

   public override int Invoke(int c)
   {
      return Program.add(this.a, this.b, c);
   }
}

// now our calling 
// code looks like this
int a = 1;
int b = 2;
FSharpFunc r2 = new r@9(a, b);
int r = (int)r2.Invoke((!0)3);

So in conclusion, if we’re not using currying on our functions then we get a “standard” function and once we start currying only then do we get the equivalent of sub-functions being created.

Currying functions

Currying is probably better known within functional languages. In it’s simplest form we can view a currying as a way to declare a function and if a user of the function supplies less arguments than expected then a function is returned which takes the remaining arguments.

Let’s look at currying using a functional language such as F# first, as this really shows the usefulness of such a capability. We’ll define an add function which takes three parameters

let add a b c = a + b + c

Now we can write code such as

let r = add 1 2

Note: when we create a new function from our curried function, such as r in above, we can call this a partially applied function.

As you can see, we have not supplied all the arguments and hence r is not an integer but is instead a function which now accepts a single argument, i.e. the final argument the add function expects. Therefore we can write the following code against the returned function

let i = r 3

Now, i is an integer and contains the result of add 1 2 3 function call (i.e. the value 6).

Currying comes “built-in” syntactically in languages such as F#. We can write explicit code to demonstrate what in essence happens when we work within currying capable languages. Here’s an F# example which shows how we create functions returning functions along with closures to pass the preceding function arguments to each inner function

let add a = 
    let add1 b = 
        let add2 c = 
            a + b + c
        add2
    add1

Note: The F# compiler does NOT create the code equivalent to the above when we create functions unless the usage of the add method includes using it in a curried scenario.

The above is written in F# but you’ll notice that this same technique can easily be written in languages such as C#, Java etc. Here’s the same code in a verbose implementation in C#

public static Func<int, Func<int, int>> Add(int a) => 
   new Func<int, Func<int, int>>(b => (c => a + b + c));

Thankfully C# allows a less verbose syntax, so the above can be rewritten as

public static Func<int, Func<int, int>> Add(int a) =>
   b => (c => a + b + c);

To call such a function we’d need to write code such as

var i = Add(1)(2)(3)

This is not as elegant as the F# code (in my opinion) but does allow currying and partially applied functions in C#.

As you’d expect – another functional language, Scala, supports currying using the following syntax

def add(a : Int)(b : Int)(c : Int) = a + b + c;

val r = add(1)(2)_
// or alternate syntax
// val r = add(1)(2)(_)
val i = r(3)

Notice that we require the _ (underscore) to ignore the third argument and we need to wrap each argument within brackets (creating parameter groups) to enable the function to be curried. The missing last argument need now be enclosed within brackets.

Scala also allows us to create partially applied functions where it’s not just the last n parameters that make up the new function. For example (let’s change the argument types to a string to the output is more obvious.

def mid(a : String)(b : String)(c : String) = a + b + c;

def m = mid("Start ")(_:String)(" End")
println(m("Hello World"))
// outputs Start Hello World End

In this case we’re making a partially applied function using the curried function mid where in usage we miss out the middle parameter in the example usage. However we must also supply the type along with the _ placeholder.