What is the difference between currying and partial application?

59,057

Solution 1

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

Solution 2

The easiest way to see how they differ is to consider a real example. Let's assume that we have a function Add which takes 2 numbers as input and returns a number as output, e.g. Add(7, 5) returns 12. In this case:

  • Partial applying the function Add with a value 7 will give us a new function as output. That function itself takes 1 number as input and outputs a number. As such:

    Partial(Add, 7); // returns a function f2 as output
    
                     // f2 takes 1 number as input and returns a number as output
    

    So we can do this:

    f2 = Partial(Add, 7);
    f2(5); // returns 12;
           // f2(7)(5) is just a syntactic shortcut
    
  • Currying the function Add will give us a new function as output. That function itself takes 1 number as input and outputs yet another new function. That third function then takes 1 number as input and returns a number as output. As such:

    Curry(Add); // returns a function f2 as output
    
                // f2 takes 1 number as input and returns a function f3 as output
                // i.e. f2(number) = f3
    
                // f3 takes 1 number as input and returns a number as output
                // i.e. f3(number) = number
    

    So we can do this:

    f2 = Curry(Add);
    f3 = f2(7);
    f3(5); // returns 12
    

In other words, "currying" and "partial application" are two totally different functions. Currying takes exactly 1 input, whereas partial application takes 2 (or more) inputs.

Even though they both return a function as output, the returned functions are of totally different forms as demonstrated above.

Solution 3

Note: this was taken from F# Basics an excellent introductory article for .NET developers getting into functional programming.

Currying means breaking a function with many arguments into a series of functions that each take one argument and ultimately produce the same result as the original function. Currying is probably the most challenging topic for developers new to functional programming, particularly because it is often confused with partial application. You can see both at work in this example:

let multiply x y = x * y    
let double = multiply 2
let ten = double 5

Right away, you should see behavior that is different from most imperative languages. The second statement creates a new function called double by passing one argument to a function that takes two. The result is a function that accepts one int argument and yields the same output as if you had called multiply with x equal to 2 and y equal to that argument. In terms of behavior, it’s the same as this code:

let double2 z = multiply 2 z

Often, people mistakenly say that multiply is curried to form double. But this is only somewhat true. The multiply function is curried, but that happens when it is defined because functions in F# are curried by default. When the double function is created, it’s more accurate to say that the multiply function is partially applied.

The multiply function is really a series of two functions. The first function takes one int argument and returns another function, effectively binding x to a specific value. This function also accepts an int argument that you can think of as the value to bind to y. After calling this second function, x and y are both bound, so the result is the product of x and y as defined in the body of double.

To create double, the first function in the chain of multiply functions is evaluated to partially apply multiply. The resulting function is given the name double. When double is evaluated, it uses its argument along with the partially applied value to create the result.

Solution 4

Interesting question. After a bit of searching, "Partial Function Application is not currying" gave the best explanation I found. I can't say that the practical difference is particularly obvious to me, but then I'm not an FP expert...

Another useful-looking page (which I confess I haven't fully read yet) is "Currying and Partial Application with Java Closures".

It does look like this is widely-confused pair of terms, mind you.

Solution 5

I have answered this in another thread https://stackoverflow.com/a/12846865/1685865 . In short, partial function application is about fixing some arguments of a given multivariable function to yield another function with fewer arguments, while Currying is about turning a function of N arguments into a unary function which returns a unary function...[An example of Currying is shown at the end of this post.]

Currying is mostly of theoretical interest: one can express computations using only unary functions (i.e. every function is unary). In practice and as a byproduct, it is a technique which can make many useful (but not all) partial functional applications trivial, if the language has curried functions. Again, it is not the only means to implement partial applications. So you could encounter scenarios where partial application is done in other way, but people are mistaking it as Currying.

(Example of Currying)

In practice one would not just write

lambda x: lambda y: lambda z: x + y + z

or the equivalent javascript

function (x) { return function (y){ return function (z){ return x + y + z }}}

instead of

lambda x, y, z: x + y + z

for the sake of Currying.

Share:
59,057
SpoonMeiser
Author by

SpoonMeiser

READY. L╮ 10 PRINT "╭───╮" 20 PRINT "│o o│" 30 PRINT "│ O │" 40 PRINT "│╰─╯│" 50 PRINT "╰───╯" READY. █

Updated on July 08, 2022

Comments

  • SpoonMeiser
    SpoonMeiser almost 2 years

    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?

  • SpoonMeiser
    SpoonMeiser over 15 years
    Interesting links, although they do offer conflicting ideas of what currying is.
  • SpoonMeiser
    SpoonMeiser over 15 years
    You're saying that partial application is when you curry a function, and use some, but not all of the resulting functions?
  • Mark Cidade
    Mark Cidade over 15 years
    more or less, yes. If you only supply a subset of the arguments, you'll get back a function that accepts the rest of the arguments
  • SpoonMeiser
    SpoonMeiser over 15 years
    Would changing a function f(a, b, c, d) to g(a, b) count as partial application? Or is it only when applied to curried functions? Sorry to be a pain, but I'm angling for an explicit answer here.
  • Mark Cidade
    Mark Cidade over 15 years
    g(a,b) would be a partial application only if g == f(a,b) and g(a',b') == f(a,b,a',b'). Partial application has to go in the order the arguments are specified
  • SpoonMeiser
    SpoonMeiser over 15 years
    But the same is not true for currying? I could translate f(a, b, c) into g(c) -> h(a) -> i(b), and that would still be currying? And then I couldn't use these functions for partial application?
  • Mark Cidade
    Mark Cidade over 15 years
    If you re-arranged the arguments like that, I guess it can still be considered currying. You can then go ahead and call g(x) and get back a function that accepts "a" and then "b" as arguments. Or call "g(c)(a)" and get back a function that accepts "b".
  • Jason Bunting
    Jason Bunting almost 14 years
    Anent your statement: Currying is converting a single function of n arguments into n functions with a single argument each - I understand just the opposite; currying is taking multiple, one-argument functions, then composing a multiple-argument function. Whereas a partially applied function is creating from a function that accepts multiple arguments a function that requires fewer, e.g. var Add = function(a,b) { return a + b; } var AddOne = partial(Add, 1); Can you cite sources for your explanation/understanding? Here is one I read: bit.ly/CurryingVersusPartialApplication
  • Jason Bunting
    Jason Bunting almost 14 years
    The first link is spot-on about the differences. Here's another one I found useful: bit.ly/CurryingVersusPartialApplication
  • Mark Cidade
    Mark Cidade almost 14 years
    @Jason: Your source says the same thing that I do—in its example, it takes a pre-curried multi-argument function defined using "define/curried" and re-composes it back uisng partial application. For a clearer definition of currying and partial application that are the same as mine, see en.wikipedia.org/wiki/Currying .
  • Jason Bunting
    Jason Bunting almost 14 years
    @Mark: I guess this is just one of those concepts that brings out the pedant in me - but an appeal to authoritative sources does little to satisfy, since they all seem to point to one another. Wikipedia is hardly what I consider an authoritative source, but I understand that it's hard to find much else. Suffice it to say that I think we both know that of which we speak and the power thereof, regardless of whether or not we can agree (or disagree) on the particulars of the vernacular! :) Thanks Mark!
  • Don Stewart
    Don Stewart over 11 years
    Currying is to do with tuples (turning a function that takes a tuple argument into one that takes n separate arguments, and vice versa). Partial application is the ability to apply a function to some arguments, yielding a new function for the remaining arguments. It is easy to remember if you just think currying == to do with tuples.
  • SpoonMeiser
    SpoonMeiser over 11 years
    Would you say that currying is a specific case of partial application then?
  • Pacerier
    Pacerier about 10 years
    @SpoonMeiser, No, currying is not a specific case of partial application: A partial application of a 2-input function is not the same as currying the function. See stackoverflow.com/a/23438430/632951 .
  • Pacerier
    Pacerier about 10 years
    @JasonBunting, Regarding your first comment, what you were talking about is decurrying. Currying is taking a multi-arg function as input and returning a chain of 1-arg functions as output. De-currying is taking a chain of 1-arg functions as input and returning a multi-arg function as output. As elaborated on stackoverflow.com/a/23438430/632951
  • Zaheer Ahmed
    Zaheer Ahmed over 9 years
    @Jon links you posted are informative, but it will be better to expand your answer and add some more info here.
  • Jon Skeet
    Jon Skeet over 9 years
    @Zaheer: This answer is over 6 years old, and the other answers already cover it. I don't think there's much to be gained from expanding this now.
  • user247702
    user247702 over 9 years
  • Jon Skeet
    Jon Skeet over 9 years
    @Stijn: Thanks for the context.
  • AlienWebguy
    AlienWebguy almost 9 years
    Can't believe you got 20 upvotes for a couple links and an admission you don't really know the difference between curry and partial application. Well played, sir.
  • Iven Marquardt
    Iven Marquardt about 8 years
    Partial application transforms a function from n-ary to (x - n)-ary, currying from n-ary to n * 1-ary. A partially applied function has a reduced scope (of application), that is, Add7 is less expressive than Add. A curried function on the other hand is as expressive as the original function.
  • Maksim Gumerov
    Maksim Gumerov over 7 years
    I believe the more distinctive trait is when we curry f(x,y,z)=>R, we get f(x) which returns g(y)=>h(z)=>R, each consuming a single argument; but when we partially apply f(x,y,z) as f(x) we get g(y,z)=>R, that is, with two arguments. If not for that trait, we could say that currying is like partial application to 0 arguments, thus leaving all arguments unbound; however in reality f() partially applied to 0 arguments is a function consuming 3 args at once, unlike curried f().
  • Maksim Gumerov
    Maksim Gumerov over 7 years
    " a partially applied function would return the result right away upon being invoke" - that's not correct, is it? when I partially apply a function, that expression returns a function, not "a result". Ok, you probably meant that this latter function, when called with the remaining arguments, returns the result, unlike digging one step down into currying. But no one actually says you have to specify all the remaining arguments: you can partially-apply the result of partial application, and that will once again be a function, not a "result"
  • fnl
    fnl almost 7 years
    Once again the correct answer isn't the first or the most voted: The simple explanation of the signature of curry vs. partial at the end of this answer is really the easiest way to resolve the question.
  • Roland
    Roland over 6 years
    The following gave me the key insight: "So currying gives you a one-argument function to create functions, where partial-application creates a wrapper function that hard codes one or more arguments."
  • Zach Mierzejewski
    Zach Mierzejewski almost 6 years
    What does the comment f2(7)(5) is just a syntactic shortcut mean? (I know very little.) Doesn't f2 already contain/"know about" 7?
  • Ogen
    Ogen over 5 years
    Someone's mad they're not Jon Skeet
  • alancalvitti
    alancalvitti about 5 years
    @Pacerier, is there a curry implementation somewhere (don't think it's in functools)
  • Prof Mo
    Prof Mo almost 5 years
    I am having a hard time with curry vs partial because in functional language, such as OCaml, there is no difference between currying and partial application. This holds because in functional languages, functions are first-class objects.
  • joel
    joel about 3 years
    "Currying is converting a single function of n arguments into n functions with a single argument each". Isn't changing a function signature f(a, b, c, d) to f(a)(b, c)(d) also currying? Do the resulting functions have to have a single argument each?
  • BitTickler
    BitTickler about 2 years
    So how does currying work in case of variable number of arguments, e.g. in Common Lisp: (defun foo (&rest args) ...). This would result in an infinite number of curried 1 argument functions, yes? I could not find a Common Lisp implementation of curry and would be curious.