-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlist.hpp
More file actions
103 lines (82 loc) · 2.42 KB
/
list.hpp
File metadata and controls
103 lines (82 loc) · 2.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#ifndef LIST_HPP
#define LIST_HPP
#include <memory>
// #include <stdexcept>
template<class T>
struct cons;
template<class T>
using list = std::shared_ptr<cons<T>>;
template<class T>
struct cons {
const T head;
const list<T> tail;
cons(T head, list<T> tail): head(std::move(head)), tail(std::move(tail)) { }
friend list<T> operator%=(T head, list<T> tail) {
return std::make_shared<cons>(std::move(head), std::move(tail));
}
template<class X, class Func>
friend X foldr(list<T> self, X x, const Func& func) {
if(!self) {
return x;
} else {
return func(self->head, foldr(self->tail, std::move(x), func));
}
}
template<class Func>
friend auto map(list<T> self, const Func& func) {
using type = typename std::result_of<Func(T)>::type;
return foldr(self, list<type>{}, [&](const T& head, list<type> tail) {
return func(head) %= tail;
});
}
template<class X, class Func>
friend X foldl(X x, list<T> self, const Func& func) {
if(!self) {
return x;
} else {
return foldl(func(std::move(x), self->head), self->tail, func);
}
}
struct iterator {
list<T> data;
iterator& operator++() { data = data->tail; return *this; }
bool operator!=(iterator other) { return data != other.data; }
auto& operator*() const { return data->head; }
};
friend iterator begin(list<T> self) { return {self}; }
friend iterator end(list<T> self) { return {nullptr}; }
friend list<T> concat(list<T> lhs, list<T> rhs) {
if(lhs) {
return lhs->head %= concat(lhs->tail, std::move(rhs));
} else {
return rhs;
}
}
friend std::size_t size(list<T> self) {
return foldr(self, 0, [](auto lhs, auto rhs) { return 1 + rhs; });
}
// // quick
// template<class What>
// friend list<T> operator||(list<T> self, What what) {
// if(self) return self;
// throw std::runtime_error(what);
// }
};
template<class Iterator>
static list<typename Iterator::value_type> make_list(Iterator first, Iterator last) {
if(first == last) {
return {};
} else {
auto head = std::move(*first++);
return head %= make_list(first, last);
}
}
template<class LHS, class RHS, class Func>
static auto zip(list<LHS> lhs, list<RHS> rhs, const Func& func)
-> list<typename std::result_of<Func(LHS, RHS)>::type> {
if(lhs && rhs) {
return func(lhs->head, rhs->head) %= zip(lhs->tail, rhs->tail, func);
}
return {};
};
#endif