Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question
18  
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. –  Codism Feb 1 '13 at 19:56
41  
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. McCann Feb 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. –  paul Feb 1 '13 at 21:44
3  
@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 Scientist Feb 2 '13 at 14:57
1  
The question generated a fairly interesting discussion on Reddit. –  Yannis Rizos Feb 8 '13 at 4:49

14 Answers 14

With curried functions you get easier reuse of more abstract functions, since you get to specialize. Let's say that you have an adding function

add x y = x + y

and that you want to add 2 to every member of a list. In Haskell you would do this:

map (add 2) [1, 2, 3] -- gives [3, 4, 5]
-- actually one could just do: map (2+) [1, 2, 3], but that may be Haskell specific

Here the syntax is lighter than if you had to create a function add2

add2 y = add 2 y
map add2 [1, 2, 3]

or if you had to make an anonymous lambda function:

map (\y -> 2 + y) [1, 2, 3]

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:

lookup1 :: [(Key, Value)] -> Key -> Value -- or perhaps it should be Maybe Value
lookup2 :: Map Key Value -> Key -> Value

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.

share|improve this answer
24  
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. McCann Feb 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!

share|improve this answer
1  
"ML-style languages do not have a notion of multiple arguments in curried or in uncurried form": in this respect, is Haskell ML-style? –  Giorgio Feb 2 '13 at 14:35
1  
@Giorgio: Yeah. –  Tikhon Jelvis Feb 2 '13 at 17:47
1  
Interesting. I know some Haskell and I am learning SML right now, so it is interesting to see differences and similarities between the two languages. –  Giorgio Feb 2 '13 at 18:02

(I'll give examples in Haskell.)

  1. 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
    
  2. 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.

  3. 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

    uncurry (++) . partition (< 10)
    

Indeed, (uncurry (++) . partition (< 10)) [4,12,11,1] evaluates to [4,1,12,11].

There are also important theoretical advantages:

  1. 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.
  2. 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.
  3. (Un)currying is closely connected to cartesian closed categories, which is a categorical way of viewing typed lambda calculi.
share|improve this answer
    
For the "much less readable code" bit, shouldn't that be mem x lst = any (\y -> y == x) lst ? (With a backslash). –  stusmith Feb 7 '13 at 10:02
    
Yes, thanks for pointing that out, I'll correct it. –  Petr Pudlák Feb 7 '13 at 10:08

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.

share|improve this answer

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.

share|improve this answer
1  
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 Jelvis Feb 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 R Feb 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 Jelvis Feb 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 R Feb 4 '13 at 14:45

Currying is not just syntactic sugar!

Consider the type signatures of add1 (uncurried) and add2 (curried):

add1 : (int * int) -> int
add2 : int -> (int -> int)

(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 int and 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!

share|improve this answer
3  
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 Scientist Feb 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. –  Peaker Feb 2 '13 at 13:15

Currying is just syntactic sugar, but you're slightly misunderstanding what the sugar does, I think. Taking your example,

fun add x y = x + y

is actually syntactical sugar for

fun add x = fn y => x + y

That is, (add x) returns a function that takes an argument y, and adds x to y.

fun addTuple (x, y) = x + y

That is a function that takes a tuple and adds its elements. Those two functions are actually quite diffent; they take different arguments.

If you wanted to add 2 to all numbers in a list:

(* add 2 to all numbers using the uncurried function *)
map (fn x => addTuple (x, 2)) [1,2,3]
(* using the curried function *)
map (add 2) [1,2,3]

The result would be [3,4,5].

If you wanted to sum each tuple in a list, on the other hand, the addTuple function fits perfectly.

(* Sum each tuple using the uncurried function *)
map addTuple [(10,2), (10,3), (10,4)]    
(* sum each tuple using curried function *)
map (fn (a,b) => add a b) [(10,2), (10,3), (10,4)]

The result would be [12,13,14].

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:

- val highestPositive = foldr Int.max 0;   
val highestPositive = fn : int list -> int 
share|improve this answer
1  
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 Scientist Feb 2 '13 at 15:01

Another thing I haven't seen mentioned yet is that currying allows (limited) abstraction over arity.

Consider these functions that are part of Haskell's library

(.) :: (b -> c) -> (a -> b) -> a -> c
either :: (a -> c) -> (b -> c) -> Either a b -> c
flip :: (a -> b -> c) -> b -> a -> c
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c

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.

share|improve this answer

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.

This is why Lisp programmers, when working in a functional style, sometimes use libraries for partial application.

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.

share|improve this answer

Currying allows flexible function composition.

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.

var builder = curry(function(input, logger, action) {
     logger.log("Starting action");
     try {
         action(input);
         logger.log("Success!");
     }
     catch (err) {
         logger.logerror("Boo we failed..", err);
     }
});
var x = "My input.";
goGatherArgs(builder)(x); // Supplies action first, then logger somewhere.

The builder variable is a function that returns a function that returns a function that takes my input that does my work. This is a simple useful example and not an object in sight.

share|improve this answer

For the function

fun add(x, y) = x + y

It is of the form f': 'a * 'b -> 'c

To evaluate one will do

add(3, 5)
val it = 8 : int

For the curried function

fun add x y = x + y

To evaluate one will do

add 3
val it = fn : int -> int

Where it is a partial computation, specifically (3 + y), which then one can complete the computation with

it 5
val it = 8 : int

add in the second case is of the form f: 'a -> 'b -> 'c

What currying is doing here is transforming a function that takes two agreements into one that only takes one returning a result. Partial evaluation

Why would one need this?

Say x on the RHS isn't just a regular int, but instead a complex computation that takes a while to complete, for augments, sake, two seconds.

x = twoSecondsComputation(z)

So the function now looks like

fun add (z:int) (y:int) : int =
    let
        val x = twoSecondsComputation(z)
    in
        x + y
    end;

Of type add : int * int -> int

Now we want to compute this function for a range of numbers, let's map it

val result1 = map (fn x => add (20, x)) [3, 5, 7];

For the above the result of twoSecondsComputation is evaluated every single time. This means it takes 6 seconds for this computation.

Using a combination of staging and currying one can avoid this.

fun add (z:int) : int -> int =
    let
        val x = twoSecondsComputation(z)
    in
        (fn y => x + y)
    end;

Of the curried form add : int -> int -> int

Now one can do,

val add' = add 20;
val result2 = map add' [3, 5, 7, 11, 13];

The twoSecondsComputation only needs to be evaluated once. To up the scale, replace two seconds with 15 minutes, or any hour, then have a map against 100 numbers.

Summary: Currying is great when using with other methods for higher level functions as a tool of partial evaluation. Its purpose cannot really be demonstrated by itself.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer
1  
How exactly does requiring a lot more stack frames to be created make things more efficient? –  Mason Wheeler Feb 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 Etherton Feb 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.) –  delnan Feb 1 '13 at 20:09

Currying depends crucially (definitively even) on the ability to return a function.

Consider this (contrived) pseudo code.

var f = (m, x, b) => ... return something ...

Let's stipulate that calling f with less than three arguments returns a function.

var g = f(0, 1); // this returns a function bound to 0 and 1 (m and x) that accepts one more argument (b).

var y = g(42); // invoke g with the missing third argument, using 0 and 1 for m and x

That you can partially apply arguments and get back a re-usable function (bound to those arguments that you did supply) is quite useful (and DRY).

share|improve this answer

protected by gnat Jul 6 at 16:41

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.