16

I am playing a little bit with functional programming and the various concepts of it. All this stuff is very interesting. Several times I have read about Currying and what an advantage it has.

But I do not get the point with this. The following source demonstrates the using of the curry concept and the solution with linq. Actually, I do not see any advatages of using the currying concept.

So, what is the advantage of using currying?

static bool IsPrime(int value)
{
    int max = (value / 2) + 1;
    for (int i = 2; i < max; i++)
    {
        if ((value % i) == 0)
        {
            return false;
        }
    }
    return true;
}

static readonly Func<IEnumerable<int>, IEnumerable<int>> GetPrimes = 
        HigherOrder.GetFilter<int>().Curry()(IsPrime);

static void Main(string[] args)
{
    int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

    Console.Write("Primes:");
    //Curry
    foreach (int n in GetPrimes(numbers))
    {
        Console.Write(" {0}", n);
    }
    Console.WriteLine();

    //Linq
    foreach (int n in numbers.Where(p => IsPrime(p)))
    {
        Console.Write(" {0}", n);
    }

    Console.ReadLine();
}

Here is the HigherOrder Filter Method:

public static Func<Func<TSource, bool>, IEnumerable<TSource>, IEnumerable<TSource>> GetFilter<TSource>()
{
    return Filter<TSource>;
}
sepp2k
  • 363,768
  • 54
  • 674
  • 675
Kai
  • 1,953
  • 2
  • 13
  • 18
  • 3
    I'm not seeing any obvious benefit other than obfuscating your code... – RQDQ Jan 11 '12 at 20:46
  • With Linq you can even write `numbers.Where(IsPrime)` – Elian Ebbing Jan 11 '12 at 20:46
  • 4
    I don't see any currying in your example code. Also, what is `HigherOrder`? – leppie Jan 11 '12 at 20:46
  • @leppie: HigherOrder is a class of my own with several helper methods. You see Currying from GetFilter() to GetPrimes(). – Kai Jan 11 '12 at 20:48
  • possible duplicate of [C# lambda - curry usecases](http://stackoverflow.com/questions/520083/c-sharp-lambda-curry-usecases) – Daniel A. White Jan 11 '12 at 20:51
  • No, I dont see it. What variable's are being captured? – leppie Jan 11 '12 at 20:52
  • @leppie the expression `HigherOrder.GetFilter().Curry()(IsPrime)` is an example of currying. The call to `Curry()` returns a delegate, which is in turn called; the argument is `IsPrime`. If the return value of `Curry()` were assigned to the variable `del`, the next statement would be `del(IsPrime);` – phoog Jan 11 '12 at 20:53
  • @leppie currying needn't capture variables. It decomposes functions. For example, `int Add(int a, int b) { return a + b; }` becomes `Func Add(int a) { return b => a + b; }` and the call site changes from `Add(1, 2)` to `Add(1)(2)` – phoog Jan 11 '12 at 20:56
  • 1
    @phoog: That sounds like a bad way of doing absolutely nothing! – leppie Jan 11 '12 at 20:56
  • @leppie in C#, I would agree with you, but in functional languages the concept is very useful. – phoog Jan 11 '12 at 20:57
  • @phoog: I still cannot see where the partial evaluation is happening in the OP's code, where it is pretty clear in your code. Edit: I would not even do this in Scheme! – leppie Jan 11 '12 at 20:58
  • Why not use [Linq to Curry](https://gist.github.com/486591/5930c57a45c99ab1e00c075cf05078500a8dd32e#file_test_classes.cs)? – CrazyDart Jan 11 '12 at 20:49

3 Answers3

41

what is the advantage of using currying?

First off, let's clarify some terms. People use "currying" to mean both:

  1. reformulating a method of two parameters into a methods of one parameter that returns a method of one parameter and
  2. partial application of a method of two parameters to produce a method of one parameter.

Clearly these two tasks are closely related, and hence the confusion. When speaking formally, one ought to restrict "currying" to refer to the first definition, but when speaking informally either usage is common.

So, if you have a method:

static int Add(int x, int y) { return x + y; }

you can call it like this:

int result = Add(2, 3); // 5

You can curry the Add method:

static Func<int, int> MakeAdder(int x) { return y => Add(x, y); }

and now:

Func<int, int> addTwo = MakeAdder(2);
int result = addTwo(3); // 5

Partial application is sometimes also called "currying" when speaking informally because it is obviously related:

Func<int, int> addTwo = y=>Add(2,y);
int result = addTwo(3);

You can make a machine that does this process for you:

static Func<B, R> PartiallyApply<A, B, R>(Func<A, B, R> f, A a)
{
    return (B b)=>f(a, b);
}
...
Func<int, int> addTwo = PartiallyApply<int, int, int>(Add, 2);
int result = addTwo(3); // 5

So now we come to your question:

what is the advantage of using currying?

The advantage of either technique is that it gives you more flexibility in dealing with methods.

For example, suppose you are writing an implementation of a path finding algorithm. You might already have a helper method that gives you an approximate distance between two points:

static double ApproximateDistance(Point p1, Point p2) { ... }

But when you are actually building the algorithm, what you often want to know is what is the distance between the current location and a fixed end point. What the algorithm needs is Func<Point, double> -- what is the distance from the location to the fixed end point? What you have is Func<Point, Point, double>. How are you going to turn what you've got into what you need? With partial application; you partially apply the fixed end point as the first argument to the approximate distance method, and you get out a function that matches what your path finding algorithm needs to consume:

Func<Point, double> distanceFinder = PartiallyApply<Point, Point, double>(ApproximateDistance, givenEndPoint);

If the ApproximateDistance method had been curried in the first place:

static Func<Point, double> MakeApproximateDistanceFinder(Point p1) { ... }

Then you would not need to do the partial application yourself; you'd just call MakeApproximateDistanceFinder with the fixed end point and you'd be done.

Func<Point, double> distanceFinder = MakeApproximateDistanceFinder(givenEndPoint);
General Grievance
  • 4,555
  • 31
  • 31
  • 45
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Eric, do you also know the name of this concept where a function returns `A` takes `B`, another function returns `B` and takes `C`, so based on this, there could be another function that takes `C` and returns `A`. I am not sure if I am explaining it correctly but it was a functional concept. – Joan Venge Jan 11 '12 at 23:15
  • 1
    @JoanVenge That's called [function composition](http://en.wikipedia.org/wiki/Function_composition). – Rodrick Chapman Jan 11 '12 at 23:22
6

The comment by @Eric Lippert on What is the advantage of Currying in C#? (achieving partial function) points to this blog post:

Currying and Partial Function Application

Where I found this the best explantion that works for me:

From a theoretical standpoint, it is interesting because it (currying) simplifies the lambda calculus to include only those functions which have at most one argument. From a practical perspective, it allows a programmer to generate families of functions from a base function by fixing the first k arguments. It is akin to pinning up something on the wall that requires two pins. Before being pinned, the object is free to move anywhere on the surface; however, when when first pin is put in then the movement is constrained. Finally, when the second pin is put in then there is no longer any freedom of movement. Similarly, when a programmer curries a function of two arguments and applies it to the first argument then the functionality is limited by one dimension. Finally, when he applies the new function to the second argument then a particular value is computed.

Taking this further I see that functional programming essentially introduces 'data flow programming as opposed to control flow' this is akin to using say SQL instead of C#. With this definition I see why LINQ is and why it has many many applications outside of pure Linq2Objects - such as events in Rx.

Community
  • 1
  • 1
Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
1

The advantage of using currying is largely to be found in functional languages, which are built to benefit from currying, and have a convenient syntax for the concept. C# is not such a language, and implementations of currying in C# are usually difficult to follow, as is the expression HigherOrder.GetFilter<int>().Curry()(IsPrime).

phoog
  • 42,068
  • 6
  • 79
  • 117
  • 3
    I think that in C# people still end up having an occasional need for currying, but they usually resolve that need by manually curry specific functions (i.e., writing a functions which return a delegates) rather than using a generic curry function. Currying is still used, just not in an automatic fashion. – Brian Jan 11 '12 at 22:14
  • @Brian that is a good point, and especially true with the advent of lambda expressions. – phoog Jan 11 '12 at 22:19