#include namespace predicates { template struct bool_const { using value = bool_const; }; // namespace helpers { template struct bool_and; template struct bool_and, B> { using value = typename B::value; }; template struct bool_and, B> { using value = bool_const; }; template struct bool_and { using value = typename bool_and::value; }; // template struct bool_not; template struct bool_not> { using value = bool_const; }; template struct bool_not { using value = typename bool_not::value; }; template struct eq; template struct eq { using value = bool_const; }; template struct eq { using value = bool_const; }; template struct cond; template struct cond, T, F> { using value = T; }; template struct cond, T, F> { using value = F; }; template struct cond { using value = typename cond::value; }; } // template using bool_and = typename helpers::bool_and::value; template using bool_not = typename helpers::bool_not::value; template using bool_or = bool_not, bool_not>>; template using eq = typename helpers::eq::value; template using ne = bool_not>; template using cond = typename helpers::cond::value; // template std::ostream &operator<<(std::ostream &stream, const bool_const &) { return stream << (B ? "true" : "false"); } } namespace numbers { template struct num { using value = num; }; // namespace helpers { template struct add; template struct add, num> { using value = num; }; template struct sub; template struct sub, num> { using value = num; }; template struct mult; template struct mult, num> { using value = num; }; template struct div; template struct div, num<0>> {}; template struct div, num> { using value = num; }; } // template using add = typename helpers::add::value; template using sub = typename helpers::sub::value; template using mult = typename helpers::mult::value; template using div = typename helpers::div::value; // template std::ostream &operator<<(std::ostream &stream, const num &) { return stream << N; } namespace predicates // inline namespace predicates { namespace helpers { template struct lt; template struct lt, num> { using value = ::predicates::bool_const; }; template struct le; template struct le, num> { using value = ::predicates::bool_const; }; template struct gt; template struct gt, num> { using value = ::predicates::bool_const<(A > B)>; }; template struct ge; template struct ge, num> { using value = ::predicates::bool_const= B>; }; } template using lt = typename helpers::lt::value; template using le = typename helpers::le::value; template using gt = typename helpers::gt::value; template using ge = typename helpers::ge::value; } using namespace predicates; template using absolute_value = typename ::predicates::cond>, sub, N>, N>; } namespace pairs { template struct pair { using value = pair; }; namespace helpers { template struct fst; template struct fst> { using value = A; }; template struct snd; template struct snd> { using value = B; }; } template using fst = typename helpers::fst

::value; template using snd = typename helpers::snd

::value; // template std::ostream &operator<<(std::ostream &stream, const pair &) { return stream << "(" << A() << ", " << B() << ")"; } } namespace lists { template struct list; struct nil {}; template struct cons {}; template<> struct list { using value = list; }; template struct list> { using value = list; }; // namespace helpers { template struct length; template<> struct length> { using value = ::numbers::num<0>; }; template struct length>> { using value = ::numbers::add<::numbers::num<1>, typename length::value>; }; // template struct head; template struct head>> { using value = Head; }; // template struct tail; template struct tail>> { using value = Tail; }; // template struct append; template struct append, List> { using value = List; }; template struct append>, List> { using value = list::value>>; }; // template class F, typename Init, typename List> struct fold; template class F, typename Init> struct fold> { using value = Init; }; template class F, typename Init, typename Head, typename Tail> struct fold>> { using value = typename fold::value, Tail>::value; }; // template class F, typename List> struct map; template class F> struct map> { using value = list; }; template class F, typename Head, typename Tail> struct map>> { using value = list::value, typename map::value>>; }; template class Cmp, typename Acc> struct partition_; template class Cmp, typename Acc> struct partition_, Cmp, Acc> { using value = Acc; }; template class Cmp, typename Acc> struct partition_>, Cmp, Acc> { using value = typename partition_, ::pairs::pair>>, ::pairs::snd>, ::pairs::pair, list>>>>>::value; }; template class Cmp> using partition = typename partition_, list>>::value; template class Cmp> struct qsort; template class Cmp> struct qsort, Cmp> { using value = list; }; template class Cmp> struct qsort>, Cmp> { using value = typename append< typename qsort<::pairs::fst>, Cmp>::value, list>, Cmp>::value>>>::value; }; } // template using lenght = typename helpers::length::value; template using head = typename helpers::head::value; template using tail = typename helpers::tail::value; template using append = typename helpers::append::value; template class F, typename Init, typename List> using fold = typename helpers::fold::value; template class F, typename List> using map = typename helpers::map::value; template class Cmp> using quick_sort = typename helpers::qsort::value; // template std::ostream &operator<<(std::ostream &, const list &); template<> std::ostream &operator<<(std::ostream &stream, const list &) { return stream << "[]"; } template std::ostream &operator<<(std::ostream &stream, const list> &) { return stream << "(" << Head() << "):" << Tail(); } } using namespace ::predicates; using namespace ::numbers; using namespace ::pairs; using namespace ::lists; template using inc = add>; template using abs_lt = lt, absolute_value>; int main() { std::cout << list() << std::endl; using test_list = list, list, list, list, list, list, list>>>>>>>>>>>>; std::cout << "length " << test_list() << " = " << lenght() << std::endl; std::cout << test_list() << " = " << head() << " ++ " << tail() << std::endl; std::cout << "5 + 8 = " << add, num<8>>() << std::endl; std::cout << "fold (+) 0 " << test_list() << " = " << fold, test_list>() << std::endl; std::cout << lt, num<2>>() << std::endl; std::cout << lt, num<20>>() << std::endl; std::cout << "map (+ 1) c = " << map() << std::endl; using new_list = append>; std::cout << new_list() << std::endl; std::cout << quick_sort() << std::endl; std::cout << quick_sort() << std::endl; std::cout << quick_sort() << std::endl; return 0; }