Currying and partial function application are important concepts in functional programming. For those new to this programming paradigm it’s often unclear how they differ and when the former should be used over the latter. In this lesson we’ll to go over both concepts in great detail and then explore several real-world examples. We’re going to use Scala in all code snippets.

Currying

In a nutshell, currying is the process of decomposing a function of multiple arguments into a chained sequence of functions of one argument. What does it mean exactly? Consider the following function that calculates the y-coordinate of a straight line:

This function has three arguments. If we want to transform it into a chain of functions each taking a single parameter we’ll have to use currying. Function f(a, b, x) can be represented as a composition of three maps each taking one argument:

Here g(x) is a function that returns another function (expression on the right side). The pipe-arrow symbol, which is equivalent to => in Scala, means that the argument x is mapped to another function (think of it as a shorter way to define a function):

Function h(b) maps b to another function:

Finally, function j(a) maps a to our initial function f(a, b, x).

Now, let’s create a function that calculates the y-coordinate for a line that goes through (0, 0) at a 45° angle:

We just converted our general function for a straight line into a curried function with “pre-set” properties that can be reused later.

Here is a more general definition of a curried function:

It’s the same thing that we defined before but without any “implementation” details. In this definition we can see that function f takes three arguments X, Y, and Z and then returns some value N. The curried version of the function returns another function that maps X to another function Y → (Z → N) that maps Y to yet another function Z → N that finally returns value N.

That was a pretty tedious explanation but it’s important to understand the essence of currying in a simple example before comparing it to partial function application. What do curried functions look like in the code? In Scala, we use multiple parameter lists to implement currying:

def line(a: Int, b: Int, x: Int): Int = a * x + b

def curriedLine(a: Int)(b: Int)(x: Int): Int = line(a, b, x)

def defaultLine(x: Int): Int = curriedLine(1)(0)(x)

defaultLine(5)
// returns `5`

The curriedLine method does all the currying work here. Its signature is Int => (Int => (Int => Int)). This means that curriedLine takes an integer as a parameter and returns another function that takes an integer as a parameter…and so on. Does it remind you of anything? It’s the exact definition of a curried function that we discovered just a few moments ago: X → (Y → (Z → N)).

In Scala you can convert any function into a curried function by applying curried to it:

def line(a: Int, b: Int, x: Int): Int = a * x + b

def curriedLine = (line _).curried

This version of curriedLine is the same as the previously defined curriedLine with the Int => (Int => (Int => Int)) signature.

Partial Function Application

Partially applied functions are really similar to curried functions at first glance but there are some significant differences. Consider our function for a straight line again:

Partial application of this function will result in another function of two arguments. The third argument is fixed, or set in advance. Here is a partially applied function with a pre-set value for a:

Here is the same thing rewritten in a more general notation:

Can you see the major difference between currying and partial function application?

Partially applied functions always return the value of the original function as opposed to sequentially mapping its arguments to nested functions until the last one returns the value of the original function.

Here is what a partially applied function looks like in Scala:

def line(a: Int, b: Int, x: Int): Int = a * x + b

def partialLine = (b: Int, x: Int) => line(2, b, x)

partialLine(0, 1)
// returns `2`

The signature of partialLine is (Int, Int) => Int, which is the same thing as (Y × Z) → N that we discovered above. A shortcut for creating a partially applied function in Scala is to use the underscore symbol:

def partialLine = line(2, _: Int, _: Int)

This code will generate the same partially applied function that we defined before.

Partially Applied Functions vs. Partial Functions

Partially applied functions are often confused with partial functions. Partial functions represent a completely different mathematical concept. In a nutshell, it describes a family of functions that don’t map all possible inputs to outputs, only focusing on a subset of inputs. In other words, a partial function f: X ↛ Y is a total function f: X′ → Y, for some subset X′ of X. In Scala it can be represented as:

val list = Seq(1, 2, 3)

list.map {
  case 1 => 1 * 2
  case 2 => 2 * 2
}

Here we pass a partial function to map that only doubles arguments 1 and 2.

In programming, it’s generally better to avoid partial functions and instead write total ones. Total functions are a lot easier to debug and it’s a lot more likely that bugs are caught at compile time instead of run time.

Use Cases

What are some useful applications of currying and partial function application in real life? The following examples are going to be more Scala-focused than the rest of the lesson but in a lot of cases they can be directly translated to other languages.

The obvious benefit of currying and partial function application is the ability to create specialized functions based on general functions without introducing new code and repetition. When should one be used over the other? Partially applied functions should be used for all specialized functions unless we are dealing with blocks, dynamic default parameter values, smart type inference, or multiple varargs. In those cases it’s better to use currying.

Blocks

Currying should be used over partially applied functions when the last argument of the method or function is a function, so we can enjoy the syntactic superiority of blocks that are so common in Scala programs. For example, take a look at the foldLeft method from the TraversableOnce Scala trait:

def foldLeft[B](z: B)(op: (B, A) => B): B = {
  var result = z
  this foreach (x => result = op(result, x))
  result
}

Currying allows us to use the block syntax anywhere in the code. Consider the following example that computes squares of integers:

Seq(1, 2, 3).foldLeft(Seq[Int]()) { (is, i) =>
  is :+ i * i
}

Without currying, the code would look like this:

Seq(1, 2, 3).foldLeft(Seq[Int](), { (is, i) =>
  is :+ i * i
})

It’s not as flexible because we can’t store or pass foldLeft(Seq[Int]()) around.

Default Parameter Values

Another good use case for currying is referring to a previous parameter default value in a subsequent parameter:

case class Resource(createdAt: Long)
case class Record()

def loadRecordsFor(r: Resource)
                  (since: Long = r.createdAt): List[Record] = ???

val r = Resource(System.currentTimeMillis)
val rs = loadRecordsFor(r)()

Here we want to load all records for a resource. By default, we’re only interested in the records that were created after the resource was created. However, in some cases we’d want to load resource records that were created, say, in the past day. In a case like that we can provide an optional parameter that will offset the search range by a custom date:

loadRecordsFor(r)(System.currentTimeMillis - 86400000)

The problem with this solution is that we still have to use an extra set of parenthesis, or a _, even if we are okay with using the default parameter value for since. If we want function calls to look even cleaner we can use implicits:

case class Resource(createdAt: Long)
case class Record()

def loadRecordsFor(r: Resource)
                  (implicit since: Long = r.createdAt): List[Record] = ???

val r = Resource(System.currentTimeMillis)
val rs = loadRecordsFor(r)
Implicit Parameters

“A method with implicit parameters can be applied to arguments just like a normal method. In this case the implicit label has no effect. However, if such a method misses arguments for its implicit parameters, such arguments will be automatically provided.”—Tour of Scala

This way, thanks to Scala syntactic sugar, function calls remain clean, yet we have the ability to set a custom parameter. Currying is the only way to use implicit parameters in Scala. Gor example, this won’t compile:

def loadRecordsFor(r: Resource, implicit since: Long)

Type Inference

Currying is useful for type inference. Consider the following function:

def customOp[T](a: T, b: T, op: (T, T) => T) = op(a, b)

Say, we want to make a function call like this:

customOp(2, 3, (a, b) => a + b)

The compiler will throw an error about insufficient type information. We’d have to specify types by hand:

customOp[Int](2, 3, (a, b) => a + b)

// or like this:

customOp(2, 3, (a: Int, b: Int) => a + b)

The curried version of the function allows the compiler to infer types on its own:

def customOp[T](a: T, b: T)(op: (T, T) => T) = op(a, b)

customOp(2, 3)((a, b) => a + b)

// or even shorter:

customOp(2, 3)(_ + _)

This works because the curried function is executed in two “stages” making the compiler infer types twice (once for each set of arguments).

Varargs

Another reason to use currying is multiple varargs or varargs injected before other parameters. Let’s say we want to create a custom println method that optionally capitalizes all passed strings. Since we always want to pass strings first and only then customize the output, we’ll have to use currying:

def printlnCap(ss: String*)(implicit capitalize: Boolean = false) = {
  ss.foreach(s => println(if (capitalize) s.capitalize else s))
}

printlnCap("foo", "bar") // outputs "foo" and "bar"

printlnCap("foo", "bar")(true) // outputs "Foo" and "Bar"

Here is how multiple sets of varargs can be used with currying:

def productOfSums(as: Int*)(bs: Int*): Int = as.sum * bs.sum

productOfSums(1, 2, 3)(4, 5, 6, 7, 8)
// returns 180

Join Discussion

Subscribe to our Grokked Weekly newsletter to receive excellent engineering articles and the latest lessons from Grok Academy.