Last active
December 6, 2020 08:03
-
-
Save mrange/f1a1321b2ce5ca7c44490dfde7e1bba5 to your computer and use it in GitHub Desktop.
Church Encoded Lists C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://godbolt.org/z/55frxc | |
#include <cstdio> | |
#include <cstdlib> | |
#include <iostream> | |
#include <utility> | |
#include <vector> | |
#include <type_traits> | |
#define CPP_CEL__FORWARD(v) std::forward<decltype(v)>(v) | |
namespace cpp_cel { | |
struct unit_t {}; | |
constexpr unit_t unit; | |
template<typename TRunList> | |
struct cel { | |
// State TRunList(State, Value) | |
TRunList run_list; | |
template<typename TCtor> | |
auto operator>>(TCtor && ctor) { | |
return ctor(*this); | |
} | |
}; | |
template<typename TRunList> | |
auto make_cel(TRunList && c) { | |
return cel<std::decay_t<TRunList>> { std::forward<TRunList>(c) }; | |
} | |
// Sources | |
auto empty = make_cel([](auto && f, auto && z) { return z; }); | |
template<typename T> | |
auto singleton(T v) { | |
return make_cel([vv = std::move(v)](auto && f, auto && z) { return f(z, vv); }); | |
} | |
template<typename T> | |
auto from_range(T b, T i, T e) { | |
return make_cel([bb = std::move(b), ii = std::move(i), ee = std::move(e)](auto && f, auto && z) { | |
auto ss = CPP_CEL__FORWARD(z); | |
for (auto jj = bb; jj < ee; jj += ii) { | |
ss = f(std::move(ss), jj); | |
} | |
return ss; | |
}); | |
} | |
// Pipes | |
template<typename TCollect> | |
auto collect(TCollect m) { | |
return [mm = std::move(m)](auto && cel) { | |
return make_cel([mm, cc = CPP_CEL__FORWARD(cel)](auto && f, auto && z) { | |
auto ff = [&](auto && s, auto && v) { | |
auto ic = mm(CPP_CEL__FORWARD(v)); | |
return ic.run_list(f, CPP_CEL__FORWARD(s)); | |
}; | |
return cc.run_list(std::move(ff), CPP_CEL__FORWARD(z)); | |
}); | |
}; | |
} | |
template<typename TFilter> | |
auto filter(TFilter m) { | |
return [mm = std::move(m)](auto && cel) { | |
return make_cel([mm, cc = CPP_CEL__FORWARD(cel)](auto && f, auto && z) { | |
auto ff = [&](auto && s, auto && v) { | |
return mm(v) ? f(CPP_CEL__FORWARD(s), CPP_CEL__FORWARD(v)) : CPP_CEL__FORWARD(s); | |
}; | |
return cc.run_list(std::move(ff), CPP_CEL__FORWARD(z)); | |
}); | |
}; | |
} | |
template<typename TMap> | |
auto map(TMap m) { | |
return [mm = std::move(m)](auto && cel) { | |
return make_cel([mm, cc = CPP_CEL__FORWARD(cel)](auto && f, auto && z) { | |
auto ff = [&](auto && s, auto && v) { | |
return f(CPP_CEL__FORWARD(s), mm(CPP_CEL__FORWARD(v))); | |
}; | |
return cc.run_list(std::move(ff), CPP_CEL__FORWARD(z)); | |
}); | |
}; | |
} | |
// Sinks | |
template<typename T> | |
auto sum(T z) { | |
return [zz = std::move(z)](auto && cel) { | |
auto f = [](auto && s, auto && v) { | |
return CPP_CEL__FORWARD(s) + CPP_CEL__FORWARD(v); | |
}; | |
return cel.run_list(std::move(f), zz); | |
}; | |
} | |
template<typename TCollection> | |
auto collection() { | |
return [](auto && cel) { | |
TCollection coll {}; | |
auto f = [&coll](unit_t, auto && v) { | |
coll.push_back(CPP_CEL__FORWARD(v)); | |
return unit; | |
}; | |
cel.run_list(std::move(f), unit); | |
return coll; | |
}; | |
} | |
auto print_cel = [](auto && cel) { | |
auto f = [](unit_t, auto && v) { | |
std::cout << CPP_CEL__FORWARD(v) << std::endl; | |
return unit; | |
}; | |
return cel.run_list(std::move(f), unit); | |
}; | |
} | |
int main() { | |
using namespace cpp_cel; | |
auto cel = | |
from_range(0, 1, 10) | |
>> map([](int i) { return i + 1; }) | |
>> collect([](int i) { return from_range(0, 1, i); }) | |
>> filter([](int i) { return (i & 1) == 0;}) | |
; | |
auto res = cel >> sum(0); | |
std::printf("Result: %d\n", res); | |
/* | |
auto vec = cel >> collection<std::vector<int>>(); | |
cel >> print_cel; | |
*/ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment