I was not using the latest C++ standard for a while, today I want to implement a Haskell style List
in C++ and come up with something like the following:
template<typename T>
class List {
private:
std::function<std::tuple<T,List<T>>()> f;
List() {}
List(T h, List<T> t) :f([h, t]() { return std::make_tuple(h, t); }) {}
public:
typedef T item_type;
static List<T> empty();
static List<T> cons(T h, List<T> t);
template<typename N, typename C>
static auto on(N n, C c) -> decltype(N());
};
template<typename T>
List<T> List<T>::empty() {
return List();
}
template<typename T>
List<T> List<T>::cons(T h, List<T> t) {
return List([h, t](std::function<void(T, List<T>)> c) {f(c); });
}
template<typename T>
template<typename N, typename C>
auto List<T>::on(N n, C c) -> decltype(N()) {
if (f == nullptr) return n();
else {
T h;
List<T> t;
std::tie(h, t) = f();
return c(h, t);
}
}
template<typename T, typename R, typename F>
R foldr(List<T> l, F f, R b) {
return l.on([b]() { return b; }, [f, b](T h, List<T> t) { return foldr(t, f, f(t, b)); });
}
The code compiles (VC 2015, not tested yet), but makes me a while to figure out the correct grammar for the function on
. This is the first time I saw something like this in C++, and the double template
keyword looks strange enough to me.
Question
Is this the normal way when we declare static generic methods that uses template variable not available through the class template? Can anyone point me out some clauses in the standard?