
What is the advantage of currying? - laurent123456
http://programmers.stackexchange.com/q/185585/33606
======
crntaylor
Here's a line of code taken from a (Haskell) Game of Life simulation I was
writing just a couple of days ago [0]:

    
    
      showGrid (Grid _ ((_,b),(_,b')) arr) =
          L.intercalate "\n" $ cut (b'-b+1) $ map toChar $ elems arr
    

This is the full code to convert a state of the board to a string, ready to be
printed to stdout. It consists of a chain of four function applications, which
respectively

1\. Get the elements of the array as a list (elems)

2\. Convert each element to a char (map toChar ... toChar is defined elsewhere
- it's also a one-liner).

3\. Cut the list into sublists of the correct length (cut (b'-b+1)).

4\. Join the lists together into a single string, separating them with
newlines (L.intercalate "\n").

Three of the four functions are curried. I contend that without currying by
default, it would take more resources (in terms of lines, characters and
mental effort) to write this function.

[0] <https://github.com/chris-taylor/Life>

~~~
taeric
Of course... I think many would say that your savings in resources came at the
expense of readability. Basically, I think this falls dangerously close to
Duff's device in the argument space of currying.

~~~
crntaylor
Your first point is fair. Of course, 'readability' is extremely subjective. It
should always be judged in terms of the intended audience for the code - we'd
have to ask a Haskell programmer to be sure.

Your second point I disagree with completely. Duff's device is non-idiomatic C
that relies on oddities of C syntax (fall-through of cases in a switch
statement, and the ability to jump into the middle of a loop). My code is
reasonably idiomatic Haskell.

~~~
taeric
Apologies, I should have made the second point more on the humor side than
not.

I should also stress that I don't think this being somewhat difficult to read
is really bad. Just saying that I would expect a lot of folks to balk at it.

------
eliben
This mainly makes me lament the fragmentation of the Stack Exchange network.
This question, in particular, should have been on Stack Overflow. IMHO this
fragmentation hurts the community. Very much.

------
michaelfeathers
I don't think that people really see the advantage of currying until they work
in an ML-derived language like Haskell. The syntax is tuned to make it easy
and you get very nice design affordances.

In languages like Scala, C#, etc., currying was an afterthought and it shows.
I actually think it's a shame that the Lisps make currying unnatural also.
Yes, they have homoiconicity, but it's a sad tradeoff.

------
jacquesm
I read all those answers and I'm either not getting it or there really is
something missing there. Isn't the big advantage that when you use currying
that all functions have an arity of '1'?

That means no more messing with varargs, named args (on the calling side),
positional args, defaults and so on, every function takes one argument and one
argument only, currying is then used to bypass the limitations of having only
one argument to work with.

~~~
rwmj
In a traditionally compiled language, currying doesn't provide varargs: the
compiler still has to know how many parameters a function takes before it can
be called. You cannot write `printf "%d" 1' expecting that at runtime printf
is going to parse the string and read further arguments, because the compiler
wouldn't know when printf can be called.

OCaml famously (or notoriously) hacks this knowledge into the compiler, so the
compiler knows about format strings and parses them. This is nicely typesafe,
but means you cannot use varargs in your own functions, and there are odd
restrictions on the format string. (You can use the camlp4 preprocessor, or
lists-as-parameters, to get around this).

~~~
chongli
Haskell has printf without using lists-as-parameters. It accomplishes this by
doing some very clever type-level trickery. The key idea is in the recursive
definition of this instance of PrintfType:

    
    
        instance (PrintfArg a, PrintfType r) => PrintfType (a -> r) where

~~~
philsnow
Your snippet got cut off, care to paste the rest? I'm guessing it works by
popping the format string and the first operand off the args, and then finding
the first formatting escape in the format string and formatting it, then
recurse.

~~~
chongli
Yeah, sorry. Here's the full snippet:

    
    
        instance (PrintfArg a, PrintfType r) => PrintfType (a -> r) where
        spr fmts args = \ a -> spr fmts (toUPrintf a : args)
    

And spr is a polymorphic function of the type:

    
    
        spr :: String -> [UPrintf] -> t
    

Essentially the way this works is that it recursively conses up a list of the
arguments, calling toUPrintf on each.

------
groue
Another perspective of currying, from a guy that is not versed in functional
programming.

I have written an expression evaluation engine whose internal implementation
only manipulates functions that have a single argument. Merely value
transformers.

It used to only interpret expressions like `f(x)`, `g(f(x))`. Later, functions
were able to return other functions, and `f(x)(y)` was allowed. However, this
last expression really looks like it would be better written `f(x,y)`. Why
force the user to use a convoluted curried syntax such as `f(x)(y)` for his
two-parameter function?

So the `f(x,y)` form has been added as a mere syntactic sugar. However the
guts of the engine are still made of single-argument functions. That can get
curried.

So currying is not only a tool for the end-user. It's also a tool for the
language implementor :-)

------
huhtenberg
It'd be nice to have a form of currying in C/C++ as applied to function
pointers. Specifically, if I have

    
    
      int foo(void * bar, int baz);
    

then I should be able to use

    
    
      foo(, 10)
    

where

    
    
      int (*)(void *)
    

is expected.

Taking it beyond constant-based specialization would obviously require a
support for closures, but I think it's a safe bet that the standard C will get
it sooner rather than later.

~~~
CJefferson
In C++11, you can write bind(f,_1,10). Not quite as neat, but not bad.

~~~
huhtenberg
A lot of things are possible with C++, but they are universally just that -
"not quite as neat".

:)

------
manojlds
The OP had not understood what currying is, and went about asking the
question. Was expecting a more well thought question. Wonder why it was
upvoted. The question itself is poor.

~~~
Kiro
The answers are worse.

~~~
tikhonj
What's wrong with the answers?

~~~
thisone
I'm betting 99% this question is coming from someone taking the coursera
"Programming Languages" course, since this week covered currying (in SML/NJ),
amongst other things.

The question is poor because it specifically gives such a simple example of
currying. You can't understand certain concepts without understanding when
they are used, and when they aren't.

If the OP had instead said "I don't understand why List.foldl is curried
instead of just accepting a tuple." Then you'd see a more productive
discussion. Perhaps touching on the differences between functional language
implementations.

As it is, since the question isn't formulated well, the answers are all over
the place.

------
virmundi
I've been reviewing OO patterns for my class. I've also studied Scala a bit in
the last year. One thing currying seems to look like is a builder pattern for
functional programming. I can start with a function that requires N number of
different arguments. I can use currying to accumulate specific setting for the
function over time. Eventually when I get everything actually required for the
function, I can invoke it.

------
jonjacky
"Fields in Physics are like Curried Functions, or Physics for Functional
Programmers" - 1994 paper by Gary Leavens

[http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.49.1...](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.49.1181)
(also, full paper .ps at author's web page)

------
egonschiele
Aha, finally a place to show off my curry gem for Ruby!
<https://github.com/egonSchiele/Curry>

Note: this was written purely for fun, don't use it in a real project!

------
markov_twain
Why has arithmetic become the universal example of currying and partial
function application?

Examples: "Currying", Section 9.3 of Programming in Scala (addition); Ruby
1.9.3 documentation for Proc#curry <http://www.ruby-
doc.org/core-1.9.3/Proc.html#method-i-curry> (addition); "Currying" at the
Haskell Wiki <http://www.haskell.org/haskellwiki/Currying> (division);
"Currying" at Wikipedia
[http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_...](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application)
(division); "Currying" at c2 wiki
<http://c2.com/cgi/wiki?CurryingSchonfinkelling> (addition, multiplication);
PEP 0309 for adding curry to Python <http://www.python.org/dev/peps/pep-0309/>
(addition); this StackExchange post; etc.

Surprisingly, searching for currying in JavaScript returns this John Resig
post with actually useful examples: <http://ejohn.org/blog/partial-functions-
in-javascript/> although they still have no advantage over doing partial
application by just defining a new function.

The only situation in which I've ever thought to myself "I know, I'll use
curried functions," was in passing a set of data through a bunch of filters
with different arities.

To take an example from HN's front page today, say you want to take some map
of key value pairs, grab all the keys, convert them to strings, reject
duplicates, sort them alphabetically, and finally concatenate them separated
by commas.

Let's assume you have the following functions available (in pseudocode):

    
    
      keys(map) -> vector
      flatmap(func, vector) -> vector
      tostring(anything) -> string
      sort(sort-func, vector) -> vector
      compare-strings(string, string) -> first-is-greater, theyre-equal, or last-is-greater
      unique(compare-func, vector) -> vector
      concat(separator, vector) -> vector
    

and assume you have some way of connecting a list of these filter functions
together like pipes, where the output of each function becomes the input of
the next:

    
    
      reduce(composing-func, list-of-filter-functions, initial-input) -> final-result
    

Here, the composing-func takes two arguments: input, which is the output of
the last iteration (or initial-input); and filter, which represents each
function that will be applied in turn to produce some output. Notice that each
filter function must take exactly one argument, which matches the return type
of the previous filter-function in the pipeline.

    
    
      composing-func = (previous-result, filter) -> {
        apply(filter, previous-result)
      }
    

Now looking at our available functions, we can use currying and partial
function application to pre-fill-in some arguments needed so that their input
and output types line up:

    
    
      list-of-filter-functions = [
        flatmap(keys),
        map(tostring),
        unique(compare-strings),
        sort(compare-strings),
        concat(",")
      ]
    

And actually, we're now done. All of our filter functions have been partially
applied as a sort of initialization for a complicated pipeline.

I'm guessing that currying and partial function application are useful in
building parsers (like haskell & scala's parser combinators) but I don't know.

~~~
bcoates
I think people use currying with arithmetic examples because currying gives
you general partial application if your function is commutative, and almost
the only commutative functions in real programs are arithmetic and some
comparison functions.

It's kind of weird because the more arguments your function has, the more
useful partial application is, and the less likely the curried form is going
to work without reordering.

------
dschiptsov
You can write fancy code in Haskell and then write long, narcissistic blog
posts.)

Seriously, it is all about closures - you could capture (and delay) the
computation, like creating a closure (a function with its parameters) and then
actually execute the code when some other conditions were meet. Currying
allows you to execute all steps but last one, for example, so you will have a
returned function to call whenever you wish.

------
guard-of-terra
Currying is a functional approach. But there is an object-oriented approach
that works even better: You have a Function add object that has methods
bindWith1(x) and bindWith2(y) both returning a function of one argument.

With add they do the same but with say divide they do different things (both
useful).

~~~
michaelfeathers
Yes, you can do that, but to me it's not as nice as having as syntax that
makes it easy and natural. This is where the ML-derived languages like OCaml,
F# and Haskell beat other functional languages, in my opinion.

You can argue that it's nice to be able to choose the argument to bind, but I
think that's actually a bad feature. It gets rid of the design pressure to
pick an order of arguments that maximizes easy composition.

~~~
guard-of-terra
My experience with clojure/haskell tells me that order of arguments of common
functions feels horribly wrong sometimes.

~~~
michaelfeathers
I guess there are no guarantees. Which ones are you thinking of in Haskell?
There it seems to matter more.

~~~
guard-of-terra
I always seem to struggle with array/list indexing functions.

~~~
crntaylor
Like these?

    
    
      > let lst = [1,2,3]
      > lst!!0
      1
      > lst!!1
      2
      > let arr = listArray (0,2) [1,2,3]
      > arr!0
      1
      > arr!2
      2
    

I don't see how it would be particularly helpful to have the arguments to the
indexing functions the other way around, but in case you really like the index
coming before the list/array, you can always do

    
    
      > (!0) arr
      1
      > (!!1) lst
      2

