Curry vs Partial Application

Aug 09, 2015
functional-programming
haskell

Not talking about cooking recipes.

Image of a delicious curry.

I’ve seen people referring to partial application as currying, specially people in the Groovy community since in that language the function used for partial application is named curry.

Partial application in action using Groovy:

1| def addition = {a, b -> a + b} // function of two parameters
2| def addTwo = addition.curry(2) // fix first parameter to argument 2
3|
4| println addTwo(3) // call with the other argument 3
5| // => results in 5

The problem strikes at line 2. where it’s calling curry to the operation of partial application.

Let’s read the definitions of each of them.

So, partial application can be seen as a higher-order function that receives a function and some arguments and returns a function with those arguments fixed, let’s pretend it’s type is something like:

partial: NAryFunction → [Argument] → NAryFunction

looking at it from the typed point of view we can state that partial application of an n-ary function is another n-ary function with length [Argument] arguments less.

On the other hand currying can be seen as a higher-order function that receives an n-ary function and returns an unary function, let’s pretend it’s type is something like:

curry :: NAryFunction → UnaryFunction1 → ... → UnaryFunctionN

So it transforms a multi-argument function in a set of nested functions of one argument each and that return the nested function until all the arguments are supplied. This is done because functions of one argument are more tractable.

So as you can see from their pretended type signatures, they are completely different!

Generally what we found in most languages is partial application and in the face of partial application currying is probably not needed because is awkward to use in most imperative languages (because of the repeated function-calling syntax), take for example this snippet of JavaScript:

//
// curry and partial are fictional functions
//
let addition = (a, b) => a + b
let additionCurried = curry(addition)
// with partial application you can do more than one thing
// that is, you can fix how many arguments you need
let addTwo = partial(addition, 2)
let four = partial(addition, 2, 2)
// with currying on the other hand you have only one way
// which is give the function one argument at a time
let addTwo = additionCurried(2)
let four = additionCurried(2)(2)

See it from this point of view, a function f can be partially applied using two techniques:

  1. Partially apply the function directly: partial(f, [args…])
  2. Curry the function: curry(f) which forces you to supply the rest of the arguments one-by-one

In most languages the first option is preferred because syntactically looks better and lets you fix more than one argument at a time.

The beauty of Haskell

One of the things I like most from Haskell is its syntax, which is funny because I used to hate it and favor Lisp syntax (or lack of it :P). Haskell doesn’t have partial application, but curried functions, but thanks to Haskell syntax where function evaluation doesn’t need any special notation the use of curried functions looks just as partial application. Take for example the following:

addition a b = a + b
addTwo = addition 2
four = addition 2 2

I want you to pay special attention to this line four = addition 2 2, here addition is a curried function that cannot receive more than one argument at a time, but with Haskell’s syntax that’s transparent, it looks just as partial application, what’s really happening though is that Haskell sees that expression as (addition 2) 2, in other words, it calls addition with the argument 2 and calls again its result (addition 2) with the argument 2. This is contrary to what we see in other languages where functions and values are clearly separated and there is special syntax for evaluating a function. Take for example the same snippet of code in JavaScript:

let addition = curry((a, b) => a + b)
let addTwo = addition(2)
let four = addition(2)(2)

Here you see that since four is curried we are obligated to give it all its arguments one-by-one and because of JavaScript’s syntax the process looks kind of ugly addition(2)(2) compared to partial application partial(addition, 2, 2).

Drops of history

The name Currying was given by Christopher Strachey as a reference to Haskell Brooks Curry (the Haskell language is named after hime), an American logician known for his work in combinatory logic.

The currying technique was actually invented by Moses Schönfinkel , a Russian logician who was the inventor of combinatory logic, and it was a simplification to the work done in combinatory logic and lambda calculus that states that functions of two or more arguments can be replaced by functions taking just one argument.