Currying and partial use of a function

Published on November 27, 2009

Currying and partial use of a function

Original author: Wes Dyer
  • Transfer
When I first heard the term Currying , I immediately imagined delicious Thai and Indian cuisines. To my surprise, I found that the conversation was not about wonderful spices, but about converting a function that takes n arguments into a function that takes one argument and returns a curried function that takes n - 1 arguments. Where could it be useful?

From a theoretical point of view, this is interesting, because in lambda calculusit is easier to operate with functions that have one argument. On the practical side, this gives the programmer the opportunity to create a family of functions from the base function by fixing the first k arguments. This is similar to how we fasten something to the wall and for this we need two studs. Until we stuck a single hairpin, the object can freely move anywhere on the surface; however, movement is limited as soon as we pinned it with one hairpin. And finally, when the second hairpin is stuck in this object, the object no longer has freedom of movement. Similarly, when a programmer curries a function of two arguments and applies it to the first argument, functionality is limited to one dimension. Finally, when he applies the new function to the second argument, the final value is calculated.

In C #, this means that if I have a delegate of type Func <A, B, R> (a delegate with two arguments of types A and B respectively and returning type R), then I can create a delegate that has type Func <A, Func <B, R >>. Note that the curried delegate accepts only one argument, but returns a delegate that accepts the second argument of the original function and ultimately returns a value.

Consider the creation of such functions using the addition function as an example. We can curry addition by applying the Curry function to add. Actually, this curried add function creates functions that add to n, where n is the argument of the curried add function. For example, we can create an increment function by applying the curried add function to a value of 1.

Func<int,int,int> add = (x,y) => x + y;

Func<int,Func<int,int>>curriedAdd = add.Curry();

Func<int,int> inc = curriedAdd(1);

An incremental function when called now returns one, plus the value of its argument. Now we can use our functions for different forms of addition. So what does this Curry function look like? In fact, it is very simple. It just takes a function of two arguments and returns a lambda that captures the first argument and then the second argument. Once both arguments are provided, it calls the original function with the arguments. It is very simple to follow this pattern and create a Curry function that curries functions with a different arity. Let's look at what happens when we create each of these functions. First, we created the add function, which looks like this: After we curried add, the function takes the form:

Console.WriteLine(add(3,4)); // 7<br>
Console.WriteLine(curriedAdd(3)(5)); // 8<br>
Console.WriteLine(inc(2)); // 3

public static Func<A, Func<B, R>> Curry<A, B, R>(this Func<A, B, R> f)<br/>
    return a => b => f(a, b);<br/>

(x, y) => x + y

x => y => x + y
We created inc by calling curried add with a value of 1. This essentially creates a function like this:
y => 1 + y

The idea of ​​currying a function and then fixing the first n arguments of the original function can be generalized into a concept called partial application of the function. For example, if we take our add function from the previous example, we can directly create the increment from add without first creating curriedAdd. Where the Partial function is written as: Notice how the function accepts the function and the value a, which has the same type as the first argument of the function. It will return a function that takes the remaining arguments and then applies all the arguments to the original function. This can be generalized to a set of functions that produce partially applied functions.

Func<int,int> inc = add.Partial(1);

public static Func<B, R> Partial<A, B, R>(this
Func<A, B, R> f, A a)<br>
    return b => f(a, b);<br>