Currying and partial function application

C++
Author

Quasar

Published

December 11, 2024

Introduction to currying

Let \(u=f(x_1,\ldots,x_n)\) be a function of \(n\) variables. curry<n>(f) is an operator form of the function \(f\), such that:

\[ \begin{align*} \text{curry<n>}(f)(a_1)(a_2)\ldots(a_n) = f(a_1,\ldots,a_n) \end{align*} \]

and

\[ \begin{align*} \text{curry<n>}(f)(a_1) &= \text{curry<n-1>}(g(x_2,\ldots,x_n)), & \quad g(x_2,\ldots,x_n) &= f(a_1,x_2,\ldots,x_n) \\ \text{curry<n-1>}(g)(a_2) &= \text{curry<n-2>}(h(x_3,\ldots,x_n)), &\quad h(x_3,\ldots,x_n) &= g(a_2,x_3,\ldots,x_n) \end{align*} \]

C++ implementation using lambda

#include <iostream>
#include <functional>
#include <cmath>
#include <cassert>

/* curry<N>(f) is an operator form of the function of N variables,
   so that curry<N>(f)(x_1)(x_2)...(x_N) = f(x_1,...,x_N).

   Also, curry<N>(f)(a_1) = curry<N-1>(f')

   where f' is a function of N-1 variables obtained by partial
   function application, that is, substituting the value x_1=a_1 in f.
*/

template<int N>
auto curry (auto f){
    if constexpr(N == 1){
        return [=](auto x){
            return f(x);
        };
    }else{
        return [=](auto x){
            return curry<N-1>(
                [=](auto... rest){
                    return f(x, rest...);
            });
        };
    }
};

int main()
{
    auto norm = [](double x, double y, double z) -> double {
        return sqrt(x*x + y*y + z*z);
    };

    assert(curry<3>(norm)(1)(2)(2) == 3.0);
    return 0;
}

Compiler Explorer