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;
}