Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active December 6, 2020 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrange/f1a1321b2ce5ca7c44490dfde7e1bba5 to your computer and use it in GitHub Desktop.
Save mrange/f1a1321b2ce5ca7c44490dfde7e1bba5 to your computer and use it in GitHub Desktop.
Church Encoded Lists C++
// 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