Skip to content

Instantly share code, notes, and snippets.

@hidez8891
Created January 21, 2016 12:31
Show Gist options
  • Save hidez8891/1c7e0012072f410886cb to your computer and use it in GitHub Desktop.
Save hidez8891/1c7e0012072f410886cb to your computer and use it in GitHub Desktop.
C++ curried function
// (a0 -> a1 -> ... -> r) -> (a0 -> (a1 -> ... -> r))
template <typename F>
auto curry_1(F f)
{
return [f](auto a) {
return [f, a](auto... args) {
return f(a, args...);
};
};
}
// (a0 -> ... -> r) -> (a0 -> ... -> ak) -> (ak' -> ... -> r)
template <typename F>
auto curry_n(F f)
{
return f;
}
template <typename F, typename T, typename... Ts>
auto curry_n(F f, T a, Ts... args)
{
auto f1 = curry_1(f)(a);
return curry_n(f1, args...);
}
// (a0 -> a1 -> ... -> r) -> (a0 -> a1 -> ... -> r)
template <typename F, int N>
struct curry_r
{
auto operator()(F f)
{
return [f](auto... args) {
auto f1 = curry_n(f, args...);
return curry_r<decltype(f1), N - sizeof...(args)>{}(f1);
};
}
};
template <typename F>
struct curry_r<F, 1>
{
auto operator()(F f)
{
return [f](auto a) {
return f(a);
};
}
};
template <typename F>
struct curry_r<F, 0>
{
auto operator()(F f)
{
return f();
}
};
// (a0 -> a1 -> ... -> r) -> (a0 -> a1 -> ... -> r)
template <typename R, typename... Args>
auto curry(R f(Args...))
{
return curry_r<R(Args...), sizeof...(Args)>{}(f);
}
/************************
test code
************************/
#include <iostream>
#include <string>
std::string f(std::string x, std::string y, std::string z)
{
return x + y + z;
}
int main()
{
std::cout << curry(f)("a")("b")("c") << std::endl;
std::cout << curry(f)("a", "b")("c") << std::endl;
std::cout << curry(f)("a")("b", "c") << std::endl;
std::cout << curry(f)("a", "b", "c") << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment