Currying vs Partial Application

Recent­ly I have come across some real­ly inter­est­ing ques­tions and debates around these two terms and how they dif­fer from one anoth­er. There seems to be wide­spread con­fu­sions with many exam­ples demon­strates one whilst intends anoth­er, and some sim­ply uses the terms inter­change­ably.

Whilst admit­ted­ly not being a func­tion pro­gram­ming expert, I’ve spent a bit of time scour­ing the web for infor­ma­tion from those who are and I think I’ve final­ly come to under­stand the dif­fer­ence between the two!

In case you’re not famil­iar with what Cur­ry­ing and Par­tial Appli­ca­tion means, here’s some quick def­i­n­i­tions for you.

Definitions

Cur­ry­ing

Accord­ing to Wikipedia, cur­ry­ing is:

the tech­nique of trans­form­ing a func­tion that takes mul­ti­ple argu­ments in such a way that it can be called as a chain of func­tions each with a sin­gle argu­ment.

This means for a giv­en func­tion f, which takes three para­me­ters x, y, and z and returns R:

f(x, y, z) => R

once cur­ried it becomes:

curriedf(x) => g(y) => h(z) => R

When you sup­ply x to the cur­ried func­tion cur­riedf, you get back a new func­tion g, g takes a sin­gle para­me­ter and returns anoth­er func­tion h which also takes a sin­gle para­me­ter but this time returns R.

So to get the full appli­ca­tion of the orig­i­nal func­tion f, you need to call

curriedf(x)(y)(z).

With cur­ry­ing, para­me­ters must be sup­plied from left to right start­ing from the left-most para­me­ter.

Par­tial Appli­ca­tion

Again, bor­row­ing from Wikipedia, Par­tial appli­ca­tions refers to:

the process of fix­ing a num­ber of argu­ments to a func­tion, pro­duc­ing anoth­er func­tion of small­er ari­ty.

This means for a giv­en func­tion f, which takes three para­me­ters x, y, and z and returns R:

f(x, y, z) => R

If you fix the first para­me­ter x to 1 then you get anoth­er func­tion g that takes two para­me­ters and returns R:

g(y, z) => R    <=>    f(1, y, z) => R

Equal­ly if you fix both x and y to val­ues 1 and 2 respec­tive­ly then you get anoth­er func­tion h that takes one para­me­ter and returns R:

h(z) => R    <=>    f(1, 2, z) => R

Currying vs Partial Application

At first glance the sim­i­lar­i­ties are hard to miss, and one might be tempt­ed to sug­gest (well, many have!) that they are two of the same thing or that one is sim­ply a spe­cial case of the oth­er. How­ev­er, there are some cru­cial dif­fer­ences between the two which ulti­mate­ly dic­tates their very dif­fer­ent appli­ca­tions in prac­tice.

imageTo help you under­stand the dif­fer­ences, try and ignore the fact that both Cur­ry­ing and Par­tial Appli­ca­tion takes a func­tion and returns a func­tion with less input para­me­ters and instead think about the func­tion that’s returned (see image):

Cur­ry­ing

- when you cur­ry a func­tion F, you get back a chain of func­tions that returns anoth­er func­tion at every stage, except the last func­tion in the chain

- you still have to apply all the nec­es­sary para­me­ters if you want to get the full appli­ca­tion of the orig­i­nal func­tion (i.e. R)

- you have to sup­ply para­me­ters one at a time to a chain of func­tions

- you have to sup­ply para­me­ters from left to right in the same order as the orig­i­nal func­tion F

Par­tial Appli­ca­tion

- when you par­tial­ly apply a func­tion F, you get back a func­tion that allows you to get the full appli­ca­tion (i.e. R) of the orig­i­nal func­tion F with less para­me­ters

- you don’t have to sup­ply para­me­ters in any par­tic­u­lar order

Examples

So, the main dif­fer­ence between cur­ry­ing and par­tial appli­ca­tion lies in the return type of the new func­tion pro­duced, let’s see how they dif­fer­en­ti­ate in prac­tice with a sim­ple exam­ple in Javascript:

// original function that takes three parameters a1, a2 and a3
function f(a1, a2, a3) {
    return a1 + a2 + a3;
}

// curried function which takes one parameter at a time
function curry(a1) {
    // each stage takes another parameter and get you closer to the
    // full application of f
    return function (a2) {
        // but only with the inner most function do you actually get
        // the return value you wanted
        return function (a3) {
            return f(a1, a2, a3);
        };
    };
}

// partial applied function which takes one parameter and fixes
// the other 2
function partial(a1) {
    // a partially applied function of the original function f can
    // get you the full application straight away
    return f(a1, 5, 10);

}

curry(1)(5)(10); // returns 16
partial(1); // returns 16

Parting thoughts…

In gen­er­al, both tech­niques pro­duce reusable, help­ful func­tions which fix­es some para­me­ters of the orig­i­nal func­tion. For exam­ple, with Cur­ry­ing the func­tion returned at each and every stage of the chain can be reused and poten­tial­ly cre­ate a tree of func­tions:

image

though in prac­tice I can think of few exam­ples where you would require such lev­el of reusable func­tions…

I’m of the opin­ion that Par­tial Appli­ca­tion has greater appli­ca­tions (not pun intend­ed!) in solv­ing real world prob­lems. In fact, using Partial Appli­ca­tion is some­thing we’ve all done before – e.g. take a gen­er­al pur­pose func­tion which needs lots of para­me­ters and make a more high lev­el func­tion out of it by fix­ing some para­me­ters with sen­si­ble defaults:

// base method which provides a way to encapsulate common logic, but
// needs a number of parameters in order to 'tune' its behaviour
// NOTE: this C# code won't compile, it's just to illustrate a common
// pattern of using partial application
public void DoFileIoOperation(
    FileReadWriteMode mode,
    string path, string content,
    FileOverwriteMode overwriteMode)
{
    …
}

// high level methods more useful to anyone who's trying to get things done
public void DoFileRead(string path)
{
    DoFileIoOperation(
        FileReadWriteMode.Read, path, null, FileOverwriteMode.None);
}

public void DoFileWrite(string path, string content)
{
    DoFileIoOperation(
        FileReadWriteMode.Write, path, content, FileOverwriteMode.Overwrite);
}

Also, the fact that you don’t need to sup­ply each and every para­me­ters one at a time, in a par­tic­u­lar order makes Par­tial Appli­ca­tion eas­i­er to apply in prac­tice. As much as one would love to stay ‘pure’, it’s sim­ply far more prag­mat­ic to repack­age the orig­i­nal func­tion sig­na­ture and fix mul­ti­ple para­me­ters in one go!