Search code examples
language-agnosticterminologydefinitioncurryingpartial-application

What is the difference between currying and partial application?


I quite often see on the Internet various complaints that other peoples examples of currying are not currying, but are actually just partial application.

I've not found a decent explanation of what partial application is, or how it differs from currying. There seems to be a general confusion, with equivalent examples being described as currying in some places, and partial application in others.

Could someone provide me with a definition of both terms, and details of how they differ?


Solution

  • Currying is converting a single function of n arguments into n functions with a single argument each. Given the following function:

    function f(x,y,z) { z(x(y));}
    

    When curried, becomes:

    function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
    

    In order to get the full application of f(x,y,z), you need to do this:

    f(x)(y)(z);
    

    Many functional languages let you write f x y z. If you only call f x y or f(x)(y) then you get a partially-applied function—the return value is a closure of lambda(z){z(x(y))} with passed-in the values of x and y to f(x,y).

    One way to use partial application is to define functions as partial applications of generalized functions, like fold:

    function fold(combineFunction, accumulator, list) {/* ... */}
    function sum     = curry(fold)(lambda(accum,e){e+accum}))(0);
    function length  = curry(fold)(lambda(accum,_){1+accum})(empty-list);
    function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
    
    /* ... */
    @list = [1, 2, 3, 4]
    sum(list) //returns 10
    @f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
    f(0,list) //returns 10
    @g = f(0) //same as sum
    g(list)  //returns 10