Curry, Yum!
1 What is a Curried Function?
Currying is a way of taking a function of multiple arguments and returning a series of functions that take one argument. For example, consider the simple two-argument function
function sum(x, y) {
return x + y;
}
If we write sum(1, 2)
, it gives us 3.
We could instead write it as
function curried_sum(x) {
return function (y) {
return x + y;
}
}
Now, we have to call the function differently. Instead of writing sum(1, 2)
, you write curried_sum(1)(2)
, but it still gives you 3 as a result.
The obvious question to ask now is "Why on earth would I want to write functions that way?" It seems to add verbosity while still giving you the same end result. In fact, currying functions does give you a very useful tool - it allows you to partially apply your functions.
2 Partially Applied Functions
A partially applied function is what happens when you plug in some arguments to a function, but leave other arguments free. Using the example from above, we have that curried_sum(1)
is the function that adds 1 to a number. It's what happens when you take the sum
function, but fix 1 as the first argument.
This turns out to be a very useful way of defining new functions. The ++
increment operator present in many languages is essentially just curried_sum(1)
. But this idea of partially applying functions shows up in many other contexts.
2.1 Indefinite Integrals
In fact, we can actually look at the indefinite integral as a partially applied function. A definite integral is a function that takes two arguments: it takes a function to integrate, and an interval to integrate over. We usually write $\int_a^b f(x)\;dx$, but we could just as easily write definite_integral(f, [a, b])
. Now, what happens if we partially apply definite_integral
to just the first argument? definite_integral(f)
should give us a function that takes in an interval and spits out the integral of f
over that interval. And that's pretty much what the indefinite integral does! If $F(x) = \int f(x) \; dx$, then $\int_a^b f(x)\;dx = F(b) - F(a)$.
2.2 Dot Products and Dual Vectors
Now, we'll look at an example from linear algebra. Consider the real vector space $\mathbb{R}^3$. The dual vector space $\left(\mathbb{R}^3\right)^\star$ is the set of linear functions $f : \mathbb{R}^3 \to \mathbb{R}$. The Euclidean dot product on $\mathbb{R}^3$ gives us a bilinear function $g:\mathbb{R}^3 \times \mathbb{R}^3 \to \mathbb{R}^3$. For vectors $u = (u_1, u_2, u_3)$ and $v = (v_1, v_2, v_3)$, we define \[g(u, v) = u \cdot v = \sum_{i = 1}^3 u_i v_i \] Now, suppose we partially apply the dot product. $g(u, -)$ gives us a linear map $\mathbb{R}^3 \to \mathbb{R}$. This is an element of the dual space. So partial application of the dot product allows us to convert vectors to vectors in the dual space! This is a useful tool in tensor analysis (e.g. General Relativity).
2.3 Cross Products
As one last example, we'll look at the cross product of vectors in $\mathbb{R}^3$. Before we talk about the cross product, though, we have to talk about determinants. The determinant of a $3 \times 3$ matrix is signed the volume of the parallelepiped defined by its columns. We can also think of the determinant as taking in 3 vectors and returning the corresponding volume.If you've seen cross products before, you might have been taught to take the cross product of 2 vectors by taking a determinant. \[ (a_1, a_2, a_3) \times (b_1, b_2, b_3) = \begin{vmatrix} \hat \imath & \hat \jmath & \hat k \\ a_1 & a_2 & a_3 \\ b_1 & b_2 & b_3 \end{vmatrix} \]
Now, how can we make this by partially applying functions? This looks similar to a partially applied determinant. $\det(-, A, B)$ is a function that takes in a vector and returns a scalar. So it lives in the dual vector space. But, similar to what we did above, we can convert the dual vector into a regular vector. And if we do that we get the standard formula for the cross product!
We can also look at this from a different geometric perspective. The triple product of three vectors is the quantity $A \cdot (B \times C)$, and is also equal to the signed volume of the parallelepiped that they define. If we write out the formula for the cross product, we find that \[ (a_1, a_2, a_3) \cdot \begin{vmatrix} \hat \imath & \hat \jmath & \hat k \\ b_1 & b_2 & b_3 \\ c_1 & c_2 & c_3 \end{vmatrix} = \begin{vmatrix} a_1 & a_2 & a_3 \\ b_1 & b_2 & b_3 \\ c_1 & c_2 & c_3 \end{vmatrix}\] So we apply our partially applied function by taking a dot product.
You might have heard the cross product of $A$ and $B$ defined as the vector whose magnitude is the area of the parallelogram defined by $A$ and $B$ and which points perpendicular to both $A$ and $B$. We can understand this geometric definition using what we just learned. The cross product is a partially applied volume function, and you finish applying the function by dotting it with the third vector. The volume of a parallelepiped is the volume of the base times the height. If the magnitude of the cross product is the area of the base, and it points in the direction of the height, then dotting that with the third vector gives base $\times$ height. Exactly the volume we wanted!