I just learned about currying, and while I think I understand the concept, I'm not seeing any big advantage in using it.

As a trivial example I use a function that adds two values (written in ML). The version without currying would be

fun add(x, y) = x + y

and would be called as

add(3, 5)

while the curried version is

fun add x y = x + y
(* short for val add = fn x => fn y=> x + y *)

and would be called as

add 3 5

It seems to me to be just syntactic sugar that removes one set of parentheses from defining and calling the function. I've seen currying listed as one of the important features of a functional languages, and I'm a bit underwhelmed by it at the moment. The concept of creating a chain of functions that consume each a single parameter, instead of a function that takes a tuple seems rather complicated to use for a simple change of syntax.

Is the slightly simpler syntax the only motivation for currying, or am I missing some other advantages that are not obvious in my very simple example? Is currying just syntactic sugar?

It seems that you didn't get the concept of currying. I will not repeat that here as it can be easily googled. One use of currying is to get a new function from a higher order function with a captured variable.
–
CodismFeb 1 '13 at 19:56

45

Currying alone is essentially useless, but having all functions curried by default makes a lot of other features much nicer to use. It's hard to appreciate this until you've actually used a functional language for a while.
–
C. A. McCannFeb 1 '13 at 20:13

4

Something that was mentioned in passing by delnan in a comment on JoelEtherton's answer, but that I thought I would mention explicitly, is that (at least in Haskell) you can partially apply with not only functions but also type constructors -- this can be quite handy; this might be something to think on.
–
paulFeb 1 '13 at 21:44

5

@Codism I did understand what currying does, I didn't understand why it was useful. And for your example, If I understand it correctly you're talking about partial application, not currying itself.
–
Mad ScientistFeb 2 '13 at 14:57

It also allows you to abstract away from different implementations. Let's say you had two lookup functions. One from a list of key/value pairs and a key to a value and another from a map from keys to values and a key to a value, like this:

Then you could make a function that accepted a lookup function from Key to Value. You could pass it any of the above lookup function, partially applied with either a list or a map, respectively:

myFunc :: (Key -> Value) -> .....

In conclusion: currying is good, because it lets you specialize/partially apply functions using a lightweight syntax and then pass these partially applied functions around to higher order function such as map or filter. Higher order functions (which take functions as parameters or yield them as results) are the bread and butter of functional programming, and currying and partially applied functions enable higher order functions to be used much more effectively and concisely.

It's worth noting that, because of this, the argument order used for functions in Haskell is often based on how likely partial application is, which in turn makes the benefits described above apply (ha, ha) in more situations. Currying by default thus ends up being even more beneficial than is apparent from specific examples like the ones here.
–
C. A. McCannFeb 1 '13 at 21:08

The practical answer is that currying makes creating anonymous functions much easier. Even with a minimal lambda syntax, it's something of a win; compare:

map (add 1) [1..10]
map (\ x -> add 1 x) [1..10]

If you have an ugly lambda syntax, it's even worse. (I'm looking at you, JavaScript, Scheme and Python.)

This becomes increasingly useful as you use more and more higher-order functions. While I use more higher-order functions in Haskell than in other languages, I've found I actually use the lambda syntax less because something like two thirds of the time, the lambda would just be a partially applied function. (And much of the other time I extract it into a named function.)

More fundamentally, it isn't always obvious which version of a function is "canonical". For example, take map. The type of map can be written in two ways:

map :: (a -> b) -> [a] -> [b]
map :: (a -> b) -> ([a] -> [b])

Which one is the "correct" one? It's actually hard to say. In practice, most languages use the first one--map takes a function and a list and returns a list. However, fundamentally, what map actually does is map normal functions to list functions--it takes a function and returns a function. If map is curried, you don't have to answer this question: it does both, in a very elegant way.

This becomes especially important once you generalize map to types other than list.

Also, currying really isn't very complicated. It's actually a bit of a simplification over the model most languages use: you don't need any notion of functions of multiple arguments baked into your language. This also reflects the underlying lambda calculus more closely.

Of course, ML-style languages do not have a notion of multiple arguments in curried or in uncurried form. The f(a, b, c) syntax actually corresponds to passing in the tuple (a, b, c) into f, so f still only takes on argument. This is actually a very useful distinction that I wish other languages would have because it makes it very natural to write something like:

map f [(1,2,3), (4,5,6), (7, 8, 9)]

You couldn't easily do this with languages that have the idea of multiple arguments baked right in!

When using functional languages it's very convenient that you can partially apply a function. Like in Haskell's (== x) is a function that returns True if its argument is equal to a given term x:

mem :: Eq a => a -> [a] -> Bool
mem x lst = any (== x) lst

without currying, we'd have somewhat less readable code:

mem x lst = any (\y -> y == x) lst

This is related to Tacit programming (see also Pointfree style on Haskell wiki). This style focuses not on values represented by variables, but on composing functions and how information flows through a chain of functions. We can convert our example into a form that doesn't use variables at all:

mem = any . (==)

Here we view == as a function from a to a -> Bool and any as a function from a -> Bool to [a] -> Bool. By simply composing them, we get the result. This is all thanks to currying.

The reverse, un-currying, is also useful in some situations. For example, let's say we want to split a list into two parts - elements that are smaller than 10 and the rest, and then concatenate those two lists. Splitting of the list is done by partition(< 10) (here we also use curried <). The result is of type ([Int],[Int]). Instead of extracting the result into its first and second part and combining them using ++, we can do this directly by uncurrying ++ as

Currying is essential for languages that lack data types and have only functions, such as the lambda calculus. While these languages aren't useful for practical use, they're very important from a theoretical point of view.

This is connected with the essential property of functional languages - functions are first class object. As we've seen, the conversion from (a, b) -> c to a -> (b -> c) means that the result of the latter function is of type b -> c. In other words, the result is a function.

Currying may be useful if you have a function that you are passing around as a first class object, and you don't receive all of the parameters needed to evaluate it in one place in the code. You can simply apply one or more parameters when you get them and pass the result to another piece of code that has more parameters and finish evaluating it there.

The code to accomplish this is going to be simpler than if you need to get all the parameters together first.

Also, there is the possibility of more code reuse, since functions taking a single parameter (another curried function) don't have to match as specifically with all the parameters.

(In both cases, the parentheses in the type signature are optional, but I've included them for clarity's sake.)

add1 is a function that takes a 2-tuple of int and int and returns an int. add2 is a function that takes an int and returns another function that in turn takes an int and returns an int.

The essential difference between the two becomes more visible when we specify function application explicitly. Let's define a function (not curried) that applies its first argument to its second argument:

apply(f, b) = f b

Now we can see the difference between add1 and add2 more clearly. add1 gets called with a 2-tuple:

apply(add1, (3, 5))

but add2 gets called with an intand then its return value is called with another int:

apply(apply(add2, 3), 5)

EDIT: The essential benefit of currying is that you get partial application for free. Lets say you wanted a function of type int -> int (say, to map it over a list) that added 5 to its parameter. You could write addFiveToParam x = x+5, or you could do the equivalent with an inline lambda, but you could also much more easily (especially in cases less trivial than this one) write add2 5!

I understand that there is a large differenc behind the scenes for my example, but the result seems to be a simple syntactic change.
–
Mad ScientistFeb 1 '13 at 19:54

5

Currying isn't a very deep concept. It is about simplifying the underlying model (see Lambda Calculus) or in languages that have tuples anyway it is in fact about syntactic convenience of partial application. Don't underestimate the importance of syntactic convenience.
–
PeakerFeb 2 '13 at 13:15

The main motivation (at least initially) for currying was not practical but theoretical. In particular, currying allows you to effectively get multi-argument functions without actually defining semantics for them or defining semantics for products. This leads to a simpler language with as much expressiveness as another, more complicated language, and so is desirable.

While the motivation here is theoretical, I think simplicity is almost always a practical advantage as well. Not worrying about multi-argument functions makes my life easier when I program, just as it would if I was working with semantics.
–
Tikhon JelvisFeb 3 '13 at 20:41

@TikhonJelvis When you're programming, though, currying gives you other things to worry about, like the compiler not catching the fact that you passed too few arguments to a function, or even getting a bad error message in that case; when you don't use currying, the error is much more apparent.
–
Alex RFeb 4 '13 at 4:29

I've never had problems like that: GHC, at the very least, is very good in that regard. The compiler always catches that sort of issue, and has good error messages for this error as well.
–
Tikhon JelvisFeb 4 '13 at 6:35

I can't agree that the error messages qualify as good. Serviceable, yes, but they are not yet good. It also only catches that sort of issue if it results in a type error, i.e. if you later try to use the result as something other than a function (or you've type annotated, but relying on that for readable errors has its own problems); the error's reported location is divorced from its actual location.
–
Alex RFeb 4 '13 at 14:45

Curried functions are great where partial application is useful - for example map, fold, app, filter. Consider this function, that returns the biggest positive number in the list supplied, or 0 if there are no positive numbers:

I did understand that the curried function has a different type signature, and that it is actually a function that returns another function. I was missing the partial application part though.
–
Mad ScientistFeb 2 '13 at 15:01

In each case the type variable c can be a function type so that these functions work on some prefix of their argument's parameter list. Without currying, you'd either need a special language feature to abstract over function arity or have many different versions of these functions specialized for different arities.

Currying (partial application) lets you create a new function out of an existing function by fixing some parameters. It is a special case of lexical closure where the anonymous function is just a trivial wrapper which passes some captured arguments to another function. We can also do this by using the general syntax for making lexical closures, but partial application provides a simplified syntactic sugar.

Instead of (lambda (x) (+ 3 x)), which gives us a function that adds 3 to its argument, you can write something like (op + 3), and so to add 3 to every element of a some list would then be (mapcar (op + 3) some-list) rather than (mapcar (lambda (x) (+ 3 x)) some-list). This op macro will make you a function which takes some arguments x y z ... and invokes (+ a x y z ...).

In many purely functional languages, partial application is ingrained into the syntax so that there is no op operator. To trigger partial application, you simply call a function with fewer arguments than it requires. Instead of producing an "insufficient number of arguments" error, the result is a function of the remaining arguments.

I made up a function "curry". In this context, I don't care what kind of logger I get or where it comes from. I don't care what the action is or where it comes from. All I care about is processing my input.

Currying is an advantage when you don't have all of the arguments for a function. If you happen to be fully evaluating the function, then there's no significant difference.

Currying lets you avoid mentioning not-yet-needed parameters. It is more concise, and doesn't require finding a parameter name that doesn't collide with another variable in scope (which is my favorite benefit).

For example, when using functions that take functions as arguments, you'll often find yourself in situations where you need functions like "add 3 to input" or "compare input to variable v". With currying, these functions are easily written: add 3 and (== v). Without currying, you have to use lambda expressions: x => add 3 x and x => x == v. The lambda expressions are twice as long, and have a small amount of busy work related to picking a name besides x if there's already an x in scope.

A side benefit of languages based on currying is that, when writing generic code for functions, you don't end up with hundreds of variants based on the number of parameters. For example, in C#, a 'curry' method would need variants for Func<R>, Func<A, R>, Func<A1, A2, R>, Func<A1, A2, A3, R>, and so forth forever. In Haskell, the equivalent of a Func<A1, A2, R> is more like a Func<Tuple<A1, A2>, R> or a Func<A1, Func<A2, R>> (and a Func<R> is more like a Func<Unit, R>), so all the variants correspond to the single Func<A, R> case.

The primary reasoning I can think of (and I'm not an expert on this subject by any means) begins to show its benefits as the functions move from trivial to non-trivial. In all trivial cases with most concepts of this nature you'll find no real benefit. However, most functional languages make heavy use of the stack in processing operations. Consider PostScript or Lisp as examples of this. By making use of currying, functions can be stacked more effectively and this benefit becomes apparent as the operations grow less and less trivial. In the curried manner, the command and arguments can be thrown on the stack in order and popped off as needed so they are run in the proper order.

How exactly does requiring a lot more stack frames to be created make things more efficient?
–
Mason WheelerFeb 1 '13 at 19:55

1

@MasonWheeler: I wouldn't know, as I said I'm not an expert on functional languages or currying specifically. I labeled this community wiki specifically because of that.
–
Joel EthertonFeb 1 '13 at 19:58

4

@MasonWheeler Your have a point w.r.t. the phrasing of this answer, but let me chip in and say that the amount of stack frames actually created depends a lot on the implementation. For example, in the spineless tagless G machine (STG; the way GHC implements Haskell) delays actual evaluation until it accumulates all (or at least as many as it knows to be required) arguments. I can't seem to recall whether this is done for all functions or only for constructors, but I think it ought to be possible for most functions. (Then again, the concept of "stack frames" doesn't really apply to the STG.)
–
delnanFeb 1 '13 at 20:09

Partial Function Application is the process of returning a function that takes a lesser number of arguments. If you provide 2 out of 3 arguments, it'll return a function that takes 3-2 = 1 argument. If you provide 1 out of 3 arguments, it'll return a function that takes 3-1 = 2 arguments. If you wanted, you could even partially apply 3 out of 3 arguments and it would return a function that takes no argument.

So given the following function:

f(x,y,z) = x + y + z;

When binding 1 to x and partially applying that to the above function f(x,y,z) you'd get:

f(1,y,z) = f'(y,z);

Where: f'(y,z) = 1 + y + z;

Now if you were to bind y to 2 and z to 3, and partially apply f'(y,z) you'd get:

f'(2,3) = f''();

Where: f''() = 1 + 2 + 3;

Now at any point, you can choose to evaluate f, f' or f''. So I can do:

print(f''()) // and it would return 6;

or

print(f'(1,1)) // and it would return 3;

2) Currying

Currying on the other hand is the process of splitting a function into a nested chain of one argument functions. You can never provide more than 1 argument, it's one or zero.

So given the same function:

f(x,y,z) = x + y + z;

If you curried it, you would get a chain of 3 functions:

f'(x) -> f''(y) -> f'''(z)

Where:

f'(x) = x + f''(y);
f''(y) = y + f'''(z);
f'''(z) = z;

Now if you call f'(x) with x = 1:

f'(1) = 1 + f''(y);

You are returned a new function:

g(y) = 1 + f''(y);

If you call g(y) with y = 2:

g(2) = 1 + 2 + f'''(z);

You are returned a new function:

h(z) = 1 + 2 + f'''(z);

Finally if you call h(z) with z = 3:

h(3) = 1 + 2 + 3;

You are returned 6.

3) Closure

Finally, Closure is the process of capturing a function and data together as a single unit. A function closure can take 0 to infinite number of arguments, but it's also aware of data not passed to it.

Again, given the same function:

f(x,y,z) = x + y + z;

You can instead write a closure:

f(x) = x + f'(y, z);

Where:

f'(y,z) = x + y + z;

f' is closed on x. Meaning that f' can read the value of x that's inside f.

So if you were to call f with x = 1:

f(1) = 1 + f'(y, z);

You'd get a closure:

closureOfF(y, z) =
var x = 1;
f'(y, z);

Now if you called closureOfF with y = 2 and z = 3:

closureOfF(2, 3) =
var x = 1;
x + 2 + 3;

Which would return 6

Conclusion

Currying, partial application and closures are all somewhat similar in that they decompose a function into more parts.

Currying decomposes a function of multiple arguments into nested functions of single arguments that return functions of single arguments. There's no point in currying a function of one or less argument, since it doesn't make sense.

Partial application decomposes a function of multiple arguments into a function of lesser arguments whose now missing arguments were substituted for the supplied value.

Closure decomposes a function into a function and a dataset where variables inside the function that were not passed in can look inside the dataset to find a value to bind against when asked to evaluate.

What's confusing about all these is that they can kind of each be used to implement a subset of the others. So in essence, they're all a bit of an implementation detail. They all provide similar value in that you don't need to gather all values upfront and in that you can reuse part of the function, since you've decomposed it into discreet units.

Disclosure

I'm by no means an expert of the topic, I've only recently started learning about these, and so I provide my current understanding, but it could have mistakes which I invite you to point out, and I will correct as/if I discover any.