Currying Schonfinkelling

It's really just called currying, but that's not a Wiki Name. Currying is a property of functions discovered by Moses Schoenfinkel in 1924. However at the time, Haskell Curry got most of the good press about Functional Programming so it was named after him. The term itself was supposedly invented by Christopher Strachey.

If you read the FAQ, you'll see that the property described (the isomorphism of AxB->C with A->B->C) was a "well known fact" well before Schoenfinkel and Curry. Their contributions were apparently in the area of the Ess And Kay Combinators.

Currying is the concept that functions of multiple arguments are really just Higher Order Functions which take one argument and return functions. In a sort of Javaish syntax, Here are examples:

// two arg version int sum(int a, int b) { return (a+b); }

// one arg version int sum(int a) { return int sum1(int b) { return (a+b); } }

// optimised multiplication int mult(int a, int b) { select (a) { case -1: return int neg(int b) { return -b; } case 0: return int zero(int b) { return 0; } case 1: return int ident(int b){ return b; } default: return int std(int b) { return a*b; } } }

In fact you could write that in legitimate Java Script:

// two arg version var sum = function(a, b) { return (a+b); }

// one arg version var sum = function(a) { return function(b) { return (a+b); }} // Which would be used as, e.g., var plusfour = sum(4); var six = plusfour(2); var alsosix = sum(4)(2);

// optimised multiplication function mult(a) { switch(a) { case -1: return function(b) { return -b; } case 0: return function(b) { return 0; } case 1: return function(b) { return b; } default: return function(b) { return a*b; } } } var answer = mult(6)(9);


"And why would I care?"

But now I see an application of this:

This idea is used quite heavily in the Synthesis Os. You see, if the value of "a" is known at one point in the run, and we intend to add lots of "b" values to it, then Synthesis Os calls "sum(int a)", which generates the code to do "sum1(int b)" -- where 'a' is a constant. This is called Partial Evaluation. It gives Synthesis Os a substantial performance boost, as it can do code optimization based on the value of 'a'. Like, if 'a' happens to be zero, it generates/returns the code "int sum1(int b) { return b; }", optimizing the addition right out. Likewise, if 'a' is one, it generates/returns the function "int sum1(int b) { return ++b; }". Fast. Very fast. (See the paper on Synthesis Os. It claims "10 times faster than Unix.") -- Jeff Grigg

"And why would I care?"

Because it makes programming much easier and programs much easier to understand. For example, here's a piece of Haskell code to double all elements of a list:

double aList = map (* 2) aList

That is, to double a list, apply "* 2" to each element -- the * operator has been curried.

And this definition can itself be curried, so that:

double = map (* 2)

Is that really that much easier to understand than

@alist = map {$_ * 2} @alist;

...But that code does not define a new function.

But it does define a Perl Language block, which, if I understand correctly, is a code object with a lot of the same properties as a scheme closure.

(No, it doesn't; it defines an array, "@alist". But it does so in terms of the block '{$_ * 2}', which is in effect an anonymous function)

To elaborate:

double = map (* 2)

list1 = [1, 2, 3, 4, 5] list2 = [10, 20, 30, 40, 50]

double list1 >[2, 4, 6, 8, 10]

double list2 >[20, 40, 60, 80, 100]

In the Fortran Language this particular (and many similar problems) can be reduced to

A = A * 2

where A is a arbitrarily shaped array. But that is not the point.


You can curry objects too.

For example, instead of sending

window drawCircleAt:
10@10 Colour: #red

window drawCircleAt:
20@20 Colour: #red

window drawCircleAt:
30@30 Colour: #red

you can curry away the Colour argument, making a new object called a pen.

pen := window pen colour:
#red

pen drawCircleAt:
10@10

pen drawCircleAt:
20@20

pen drawCircleAt:
30@30

Curried Object is a generalisation of a number of other patterns, like Abstract Session, Iterator Pattern, as well as pens in graphics systems.

Given historical precedent, Abstract Session, Iterator Pattern, and graphics system pens are more like specialisations of, or at least attempts to emulate aspects of, curried objects. Other patterns seem to be trying to hark back to currying; for example, is Visitor Pattern much more than curried traversal?

I sometimes get the feeling that one of the things that has been forgotten (or at least, was forgotten: there seems to be some attempt to recapture the idea in recent times) by the designers of OO languages is that functions are objects, too. A lot of Design Patterns - Visitor Pattern, Strategy Pattern, Decorator Pattern, Adapter Pattern, ... - seem like techniques for transporting functions from one object to another. Currying recognises that functions can be constructed in a series of steps.

Thank you. There is quite a lot of information on this wiki about this. One starting point is the work of Thomas Kuehne in Functional Pattern System For Object Oriented Design. There is also the work FC++ (Functoids In Cpp), an attempt to implement in Cee Plus Plus a lot of things found in Haskell Language. -- John Fletcher


See original on c2.com