Skip to content

Instantly share code, notes, and snippets.

@cblp
Last active October 20, 2017 15:48
Show Gist options
  • Save cblp/725398dcfbc716d900f79b7ef36dc7a9 to your computer and use it in GitHub Desktop.
Save cblp/725398dcfbc716d900f79b7ef36dc7a9 to your computer and use it in GitHub Desktop.
#include <functional>
#include <iostream>
using namespace std;
using namespace std::placeholders;
template <typename A, typename B, typename C>
function<function<C(B)>(A)> curry(function<C(A, B)> f) {
return [=](A a){ return [=](B b){ return f(a, b); }; };
}
template <typename A, typename B, typename C>
function<C(B, A)> uncurry(function<function<C(B)>(A)> f) {
return [=](A a, B b){ return f(a)(b); };
}
template <typename A>
void print(A a) { cout << a << endl; }
void test1() {
function<int(int, int)> mul_pair = [](int x, int y) { return x * y; };
print(mul_pair(6, 7));
auto mul_curried = curry(mul_pair);
print(mul_curried(6)(7));
auto mul_pair_partially_applied = bind(mul_pair, 6, _1);
print(mul_pair_partially_applied(7));
auto mul_curried_applied = mul_curried(6);
print(mul_curried_applied(7));
auto mul_uncurried = uncurry(mul_curried);
print(mul_uncurried(6, 7));
}
template <template <typename, typename> typename F>
struct Curry {
template <typename A>
struct type1 { template <typename B> using type = F<A, B>; };
template <typename A> using type = type1<A>;
};
template <template <typename> typename F>
struct Uncurry {
template <typename A, typename B>
using type = typename F<A>::template type<B>;
};
template <int val> struct Value { static const auto value = val; };
template <typename X, typename Y> struct MulPair {
static const int value = X::value * Y::value;
};
template <typename A>
using MulCurried = Curry<MulPair>::type<A>;
template <template <typename, typename> typename F, typename A>
struct Partial { template <typename B> using type = F<A, B>; };
template <typename B>
using MulPairPartiallyApplied = Partial<MulPair, Value<6>>::type<B>;
template <typename B> using MulCurriedApplied = MulCurried<Value<6>>::type<B>;
template <typename A, typename B>
using MulUncurried = Uncurry<MulCurried>::type<A, B>;
template <typename V> void Print() { print(V::value); }
void test2() {
Print<MulPair<Value<6>, Value<7>>>();
Print<MulCurried<Value<6>>::type<Value<7>>>();
Print<MulPairPartiallyApplied<Value<7>>>();
Print<MulCurriedApplied<Value<7>>>();
Print<MulUncurried<Value<6>, Value<7>>>();
}
int main() {
test1();
test2();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment