5
votes

I'm trying to figure out the cause and effect logics behind "Currying" and comes to the following results:

  1. Multiple arguments function can be expressed as either tuple(combining multiple arguments with different types as one argument) and list(combining multiple arguments with the same type as one argument). So all functions can be expressed as single argument function.
  2. So in Haskell, function only takes one argument。How can we implementing multiple-arguments function.
  3. Using Currying. Currying is a way to implementing multiple arguemnts function.

I think the above logic 1 -> 2 -> 3 is confusing to answer "why using currying". For statement 3, one can also combine multiple tuples or lists as single argument to implementing multiple arguments function.

It seems statement 1 is not correct reason for statement 2. What I'm sure is 2->3 is correct reasoning, but what's the reason behind 2? Why Haskell, as a functional language, only take one argument?

Most books take statement 2 as an accepted fact. Does anybody know the reason behind 2? Or does anybody know the correct logic behind "why currying"?

3
You ask, "Why use currying?", which implies that at some point somebody thought, "Let us use currying to solve a language design problem we have.". But it didn't really happen like that. Somebody thought, "Let us make a language that is simple, elegant, expressive, convenient, safe, and flexible.". The solutions to these problems are to use a lambda calculus with inductive types, a nice type system, and a somewhat unusual reduction strategy. "Use currying" is not a solution to any one of these problems, but rather a coincidentally convenient tool in the system that does solve these problems. - Daniel Wagner
If you think of tuples like product types (as in: Bool has two inhabitants, Maybe Bool has three inhabitants, (Bool, Maybe Bool) has six inhabitants), then function types are exponents. Since e^(x * y) = (e^x)^y, you can always rewrite a function with type (x, y) -> e to a similar function with type y -> (x -> e). This is currying in a nutshell. Because you can always rewrite such functions (in this case, at a relatively low cost), you don't need to make multi-parameter functions a fundamental concept, which otherwise would complicate your language definition. - user824425

3 Answers

5
votes

The decision to use currying as the preferred method of multi-argument functions was made for two reasons. Firstly, Haskell has its roots firmly in lambda calculus, which uses currying. Secondly, currying allows for easy partial application, a language facet which is indescribably useful.

4
votes

The function

f x y = x + y

has the type (assuming x & y are Integers)

f :: Integer -> Integer -> Integer

this is the same as

g :: Integer -> (Integer -> Integer)

Which means f is a function that takes an Integer and returns a new function that also takes an Integer and returns an Integer. Currying is the process whereby a function that takes multiple arguments is actually evaluated as a series of functions that take one argument.

Currying makes it very easy to partially apply functions as follows

plusTwo :: Integer -> Integer
plusTwo = f 2

The above code simply applies 2 to f and binds the name plusTwo to the resulting function.

This makes it extremely easy for developers to abstract common behavior into a single place.

3
votes

First thing first, you need to remember Haskell is entirely based on Lambda Calculus. It is made upon scientific programming model (even though it doesn't means the language has only scientifical uses).

What I think you got wrong, is that does not gets only one argument because it can be shown as a tuple or list, even though that would be a pretty clever explanation.

Haskell only takes one argument because of Currying:

f(x,y) = f(x)(y)

Where f(x) returns a function that takes one argument. Currying is this whole "Functions that returns functions" scheme. So, when you f(x)(y) you are actually passing down 'y' to the 'f(x)' function.

Classical example:

add :: a->(a->a)
add(x) = x'+'

As the '+' is a function, which means it takes another argument, we can:

add(3)(5) == 8

We are not passing both arguments to add, only one so it can generate '+' which gets another argument.

After you grook that, will make a lot of sense and we can proceed on why.

Well, mostly syntatic sugar, but a very powerfull one. For example, we can define functions based on other without specifying the arguments:

add = '+'

And suddenly I assigned values to functions without mentioning the arguments (supposing of course their type declaration matches). This has lots of other possibilities and eases abstraction a lot.

Here there are good answers with good examples: https://softwareengineering.stackexchange.com/questions/185585/what-is-the-advantage-of-currying