What Is 'Currying'

What is 'Currying'?

Currying is when you break down a function that takes multiple arguments into a series of functions that each take only one argument. Here's an example in JavaScript:

function add (a, b) {
return a + b;
}

add(3, 4); // returns 7

This is a function that takes two arguments, a and b, and returns their sum. We will now curry this function:

function add (a) {
return function (b) {
return a + b;
}
}

This is a function that takes one argument, a, and returns a function that takes another argument, b, and that function returns their sum.

add(3)(4);

var add3 = add(3);

add3(4);

The first statement returns 7, like the add(3, 4) statement. The second statement defines a new function called add3 that will add 3 to its argument. (This is what some may call a closure.) The third statement uses the add3 operation to add 3 to 4, again producing 7 as a result.

What is the difference between currying and partial application?

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

What is currying in F#?

Basically, every function in F# has one parameter and returns one value. That value can be of type unit, designated by (), which is similar in concept to void in some other languages.

When you have a function that appears to have more than one parameter, F# treats it as several functions, each with one parameter, that are then "curried" to come up with the result you want. So, in your example, you have:

let addTwoNumbers x y = x + y

That is really two different functions. One takes x and creates a new function that will add the value of x to the value of the new function's parameter. The new function takes the parameter y and returns an integer result.

So, addTwoNumbers 5 6 would indeed return 11. But, addTwoNumbers 5 is also syntactically valid and would return a function that adds 5 to its parameter. That is why add5ToNumber 6 is valid.

Is currying the same as overloading?

Currying is not specific to functional programming, and overloading is not specific to object-oriented programming.

"Currying" is the use of functions to which you can pass fewer arguments than required to obtain a function of the remaining arguments. i.e. if we have a function plus which takes two integer arguments and returns their sum, then we can pass the single argument 1 to plus and the result is a function for adding 1 to things.

In Haskellish syntax (with function application by adjacency):

plusOne = plusCurried 1
three = plusOne 2
four = plusCurried 2 2
five = plusUncurried 2 3

In vaguely Cish syntax (with function application by parentheses):

plusOne = plusCurried(1)
three = plusOne(2)
four = plusCurried(2)(2)
five = plusUncurried(2, 3)

You can see in both of these examples that plusCurried is invoked on only 1 argument, and the result is something that can be bound to a variable and then invoked on another argument. The reason that you're thinking of currying as a functional-programming concept is that it sees the most use in functional languages whose syntax has application by adjacency, because in that syntax currying becomes very natural. The applications of plusCurried and plusUncurried to define four and five in the Haskellish syntax merge to become completely indistinguishable, so you can just have all functions be fully curried always (i.e. have every function be a function of exactly one argument, only some of them will return other functions that can then be applied to more arguments). Whereas in the Cish syntax with application by parenthesised argument lists, the definitions of four and five look completely different, so you need to distinguish between plusCurried and plusUncurried. Also, the imperative languages that led to today's object-oriented languages never had the ability to bind functions to variables or pass them to other functions (this is known as having first-class functions), and without that facility there's nothing you can actually do with a curried-function other than invoke it on all arguments, and so no point in having them. Some of today's OO languages still don't have first-class functions, or only gained them recently.

The term currying also refers to the process of turning a function of multiple arguments into one that takes a single argument and returns another function (which takes a single argument, and may return another function which ...), and "uncurrying" can refer to the process of doing the reverse conversion.


Overloading is an entirely unrelated concept. Overloading a name means giving multiple definitions with different characteristics (argument types, number of arguments, return type, etc), and have the compiler resolve which definition is meant by a given appearance of the name by the context in which it appears.

A fairly obvious example of this is that we could define plus to add integers, but also use the same name plus for adding floating point numbers, and we could potentially use it for concatenating strings, arrays, lists, etc, or to add vectors or matrices. All of these have very different implementations that have nothing to do with each other as far as the language implementation is concerned, but we just happened to give them the same name. The compiler is then responsible for figuring out that plus stringA stringB should call the string plus (and return a string), while plus intX intY should call the integer plus (and return an integer).

Again, there is no inherent reason why this concept is an "OO concept" rather than a functional programming concept. It simply happened that it fit quite naturally in statically typed object-oriented languages that were developed; if you're already resolving which method to call by the object that the method is invoked on, then it's a small stretch to allow more general overloading. Completely ad-hoc overloading (where you do nothing more than define the same name multiple times and trust the compiler to figure it out) doesn't fit as nicely in languages with first-class functions, because when you pass the overloaded name as a function itself you don't have the calling context to help you figure out which definition is intended (and programmers may get confused if what they really wanted was to pass all the overloaded definitions). Haskell developed type classes as a more principled way of using overloading; these effectively do allow you to pass all the overloaded definitions at once, and also allow the type system to express types a bit like "any type for which the functions f and g are defined".


In summary:

  • currying and overloading are completely unrelated
  • currying is about applying functions to fewer arguments than they require in order to get a function of the remaining arguments
  • overloading is about providing multiple definitions for the same name and having the compiler select which definition is used each time the name is used
  • neither currying nor overloading are specific to either functional programming or object-oriented programming; they each simply happen to be more widespread in historical languages of one kind or another because of the way the languages developed, causing them to be more useful or more obvious in one kind of language

Haskell currying explanation needed

Yet f takes two arguments and g only one.

No, in fact both functions take one parameter. In fact in Haskell all functions take exactly one parameter.

If you write a signature like:

f :: a ->  b -> c

then this is a less verbose form of:

f :: a -> (b -> c)

How does that work? f is a function that takes one parameter, and then returns another function that again takes a parameter.

So take for example a function add :: Int -> Int -> Int.

If we write add 5 2, we thus calculate 5 + 2. It looks like it takes two parameters, but in fact we have written (add 5) 2. We thus call the add function with 5 as parameter. This returns a function (let us call this function add5 :: Int -> Int). So this add5 function adds 5 to a number. So if we then call add5 2, then we obtain 7, since add5 returns 5 added to the parameter.

We can however construct a function (like g) that takes one parameter that is a 2-tuple, so we can use another type to pass two values as one parameter. In fact you can see g(5, 2) is actually g (5, 2): you call the function with one parameter, a 2-tuple (5, 2).

So the currying aims to transform such g function that takes one parameter (a 2-tuple) into a function f that takes again one parameter, and this will then construct a function that will take the second element of the original 2-tuple.

What are real use cases of currying?

Real use case of currying is partial application.

Currying by itself is not terribly interesting. What's interesting is if your programming language supports currying by default, as is the case in F# or Haskell.

You can define higher order functions for currying and partial application in any language that supports first class functions, but it's a far cry from the flexibility you get when every function you get is curried, and thus partially applicable without you having to do anything.

So if you see people conflating currying and partial application, that's because of how closely those concepts are tied there - since currying is ubiquitous, you don't really need other forms of partial application than applying curried functions to consecutive arguments.

Java 8 Function Style Programming what is the difference between currying and Functions Composition

While both operations output a function, the example makes the difference fairly clear:

  1. Currying takes a single function f() and produces an "intermediate" function f'() that is the same as f() but with some parameters already fixed. When you eventually fill in the rest of the parameters, you will evaluate the original f().
  2. Whereas composition will take two functions f() and g() and creates a completely different function g(f()).

Take a simple example: f(x,y) = x+y, where x and y are integers. No amount and combination of currying of this function can result in a function that will ever return a non-integer result. But compose it with g(x) = x/2, and you get g(f(x,y)) = (x+y)/2, which will of course happily return non-integers.

Why would you then use currying?

Java instance methods for example are a result of a fairly similar process. Instance methods differ from static methods in that they've got an extra hidden parameter called this. When you say new Foo(), essentially you bind this hidden parameter to the newly created Foo object. So instead of having to call function void bar(Foo this, int x), you can just refer to it as void bar(int x), with the first parameter already fixed in place. (By the way, void bar(Foo this, int x) is in fact perfectly valid Java syntax, we just almost never use it.)

This isn't entirely a coincidence, as pure functional languages can only have functions whose outputs depend on its inputs alone (as opposed to OO languages, where the output of a method can also depend on the internal state of the object the method belongs to.)

As a general advice, if you want to learn the essence of functional programming, it's best not to do it from Java. Not even from Scala either. Try to learn it from a pure functional language like Haskell and then you can come back to Java and understand much better what subset of FP was implemented in it and how.



Related Topics



Leave a reply



Submit