1use frunk::{
4 hlist::{HMappable, HZippable},
5 prelude::HList,
6 Generic, HCons, HNil, LabelledGeneric,
7};
8
9pub use self::cons_list::{ConsList, ConsListT};
10
11pub mod arithmetic_macros;
12pub mod cons_list;
13
14pub struct Poly<F>(pub F);
18
19pub trait Func<I> {
20 type Output;
21
22 fn call(&mut self, i: I) -> Self::Output;
23}
24
25impl<F: Func<I>, I> Func<I> for &mut F {
26 type Output = F::Output;
27
28 fn call(&mut self, i: I) -> Self::Output {
29 (*self).call(i)
30 }
31}
32
33impl<F: Func<Head>, Head, Tail: HMappable<Poly<F>>> HMappable<Poly<F>> for HCons<Head, Tail> {
34 type Output = HCons<<F as Func<Head>>::Output, <Tail as HMappable<Poly<F>>>::Output>;
35
36 fn map(self, mut mapper: Poly<F>) -> Self::Output {
37 let HCons { head, tail } = self;
38 HCons {
39 head: mapper.0.call(head),
40 tail: tail.map(mapper),
41 }
42 }
43}
44
45pub trait WithGeneric: Generic {
48 fn hmap<U: Generic, F>(self, f: F) -> U
49 where
50 Self::Repr: HMappable<Poly<F>, Output = U::Repr>;
51
52 fn hzip<U: Generic, TU: Generic<Repr = <Self::Repr as HZippable<U::Repr>>::Zipped>>(
53 self,
54 other: U,
55 ) -> TU
56 where
57 Self::Repr: HZippable<U::Repr>;
58
59 fn hzip_with<
60 F,
61 U: Generic,
62 TU: Generic<Repr = <<Self::Repr as HZippable<U::Repr>>::Zipped as HMappable<Poly<F>>>::Output>,
63 >(
64 self,
65 other: U,
66 f: F,
67 ) -> TU
68 where
69 Self::Repr: HZippable<U::Repr>,
70 <Self::Repr as HZippable<U::Repr>>::Zipped: HMappable<Poly<F>>;
71
72 fn hzipped_for_each<F, U: Generic>(self, other: U, f: F)
73 where
74 Self::Repr: HZippable<U::Repr>,
75 <Self::Repr as HZippable<U::Repr>>::Zipped: ForEach<F>;
76
77 fn hzip_to_list<F, U: Generic, O>(
78 self,
79 other: U,
80 f: F,
81 ) -> ConsList<O, <<Self::Repr as HZippable<U::Repr>>::Zipped as MapToList<F, O>>::Output>
82 where
83 Self::Repr: HZippable<U::Repr>,
84 <Self::Repr as HZippable<U::Repr>>::Zipped: MapToList<F, O>;
85
86 fn map_to_list<F, O>(self, f: F) -> ConsList<O, <Self::Repr as MapToList<F, O>>::Output>
87 where
88 Self::Repr: MapToList<F, O>;
89
90 fn for_each<F>(self, f: F)
91 where
92 Self::Repr: ForEach<F>;
93
94 fn fields_into_iter<U>(self) -> impl Iterator<Item = U>
96 where
97 Self::Repr: MapToList<Identity, U>;
98}
99
100pub struct Identity;
101
102impl<T> Func<T> for Identity {
103 type Output = T;
104
105 fn call(&mut self, i: T) -> Self::Output {
106 i
107 }
108}
109
110impl<T: Generic> WithGeneric for T {
111 fn hmap<U: Generic, F>(self, f: F) -> U
112 where
113 Self::Repr: HMappable<Poly<F>, Output = U::Repr>,
114 {
115 Generic::from(Generic::into(self).map(Poly(f)))
116 }
117
118 fn hzip<U: Generic, TU: Generic<Repr = <Self::Repr as HZippable<U::Repr>>::Zipped>>(
119 self,
120 other: U,
121 ) -> TU
122 where
123 Self::Repr: HZippable<U::Repr>,
124 {
125 Generic::from(Generic::into(self).zip(Generic::into(other)))
126 }
127
128 fn hzip_with<
129 F,
130 U: Generic,
131 TU: Generic<Repr = <<Self::Repr as HZippable<U::Repr>>::Zipped as HMappable<Poly<F>>>::Output>,
132 >(
133 self,
134 other: U,
135 f: F,
136 ) -> TU
137 where
138 Self::Repr: HZippable<U::Repr>,
139 <Self::Repr as HZippable<U::Repr>>::Zipped: HMappable<Poly<F>>,
140 {
141 Generic::from(Generic::into(self).zip(Generic::into(other)).map(Poly(f)))
142 }
143
144 fn hzipped_for_each<F, U: Generic>(self, other: U, f: F)
145 where
146 Self::Repr: HZippable<U::Repr>,
147 <Self::Repr as HZippable<U::Repr>>::Zipped: ForEach<F>,
148 {
149 Generic::into(self).zip(Generic::into(other)).for_each(f);
150 }
151
152 fn hzip_to_list<F, U: Generic, O>(
153 self,
154 other: U,
155 f: F,
156 ) -> ConsList<O, <<Self::Repr as HZippable<U::Repr>>::Zipped as MapToList<F, O>>::Output>
157 where
158 Self::Repr: HZippable<U::Repr>,
159 <Self::Repr as HZippable<U::Repr>>::Zipped: MapToList<F, O>,
160 {
161 Generic::into(self).zip(Generic::into(other)).map_to_list(f)
162 }
163
164 fn map_to_list<F, O>(self, f: F) -> ConsList<O, <Self::Repr as MapToList<F, O>>::Output>
165 where
166 Self::Repr: MapToList<F, O>,
167 {
168 Generic::into(self).map_to_list(f)
169 }
170
171 fn for_each<F>(self, f: F)
172 where
173 Self::Repr: ForEach<F>,
174 {
175 Generic::into(self).for_each(f)
176 }
177
178 fn fields_into_iter<U>(self) -> impl Iterator<Item = U>
179 where
180 Self::Repr: MapToList<Identity, U>,
181 {
182 self.map_to_list(Identity).into_iter()
183 }
184}
185
186pub trait WithLabelledGeneric: LabelledGeneric {
189 fn hmap<U: LabelledGeneric, F>(self, f: F) -> U
190 where
191 Self::Repr: HMappable<Poly<F>, Output = U::Repr>;
192
193 fn hzip<
194 U: LabelledGeneric,
195 TU: LabelledGeneric<Repr = <Self::Repr as HZippable<U::Repr>>::Zipped>,
196 >(
197 self,
198 other: U,
199 ) -> TU
200 where
201 Self::Repr: HZippable<U::Repr>;
202
203 fn map_to_list<F, U>(self, f: F) -> ConsList<U, <Self::Repr as MapToList<F, U>>::Output>
204 where
205 Self::Repr: MapToList<F, U>;
206
207 fn for_each<F>(self, f: F)
208 where
209 Self::Repr: ForEach<F>;
210}
211
212impl<T: LabelledGeneric> WithLabelledGeneric for T {
213 fn hmap<U: LabelledGeneric, F>(self, f: F) -> U
214 where
215 Self::Repr: HMappable<Poly<F>, Output = U::Repr>,
216 {
217 LabelledGeneric::from(LabelledGeneric::into(self).map(Poly(f)))
218 }
219
220 fn hzip<
221 U: LabelledGeneric,
222 TU: LabelledGeneric<Repr = <Self::Repr as HZippable<U::Repr>>::Zipped>,
223 >(
224 self,
225 other: U,
226 ) -> TU
227 where
228 Self::Repr: HZippable<U::Repr>,
229 {
230 LabelledGeneric::from(LabelledGeneric::into(self).zip(LabelledGeneric::into(other)))
231 }
232
233 fn map_to_list<F, U>(self, f: F) -> ConsList<U, <Self::Repr as MapToList<F, U>>::Output>
234 where
235 Self::Repr: MapToList<F, U>,
236 {
237 LabelledGeneric::into(self).map_to_list(f)
238 }
239
240 fn for_each<F>(self, f: F)
241 where
242 Self::Repr: ForEach<F>,
243 {
244 LabelledGeneric::into(self).for_each(f)
245 }
246}
247
248pub trait MapToList<F, U>: HList {
249 type Output: ConsListT<U>;
250
251 fn map_to_list(self, f: F) -> ConsList<U, Self::Output>;
254}
255
256impl<F, U> MapToList<F, U> for HNil {
257 type Output = cons_list::Nil;
258
259 fn map_to_list(self, _f: F) -> ConsList<U, Self::Output> {
260 ConsList::nil()
261 }
262}
263
264impl<F: Func<Head, Output = U>, U, Head, Tail: MapToList<F, U>> MapToList<F, U>
265 for HCons<Head, Tail>
266{
267 type Output = cons_list::Cons<U, <Tail as MapToList<F, U>>::Output>;
268
269 fn map_to_list(self, mut f: F) -> ConsList<U, Self::Output> {
270 let HCons { head, tail } = self;
271 ConsList::cons(f.call(head), tail.map_to_list(f))
272 }
273}
274
275pub trait ForEach<F>: HList {
276 fn for_each(self, f: F);
277}
278
279impl<F> ForEach<F> for HNil {
280 fn for_each(self, _: F) {}
281}
282
283impl<F: Func<Head, Output = ()>, Head, Tail: ForEach<F>> ForEach<F> for HCons<Head, Tail> {
284 fn for_each(self, mut f: F) {
285 let HCons { head, tail } = self;
286 f.call(head);
287 tail.for_each(f)
288 }
289}