1use std::fmt::{Debug, Formatter};
5use std::marker::PhantomData;
6
7pub use crate::impls::*;
8
9pub struct AsData<F>(PhantomData<F>);
11
12impl<G: Functor> AsData<G> {
13 #[inline(always)]
14 pub fn fmap<A, B, F>(f: F, fa: G::Container<A>) -> G::Container<B>
15 where
16 F: FnMut(A) -> B,
17 {
18 G::fmap(f, fa)
19 }
20}
21
22pub trait Functor {
23 type Container<T>;
24
25 fn fmap<A, B, F>(f: F, fa: Self::Container<A>) -> Self::Container<B>
26 where
27 F: FnMut(A) -> B;
28}
29
30impl Functor for Identity {
31 type Container<T> = T;
32
33 #[inline(always)]
34 fn fmap<A, B, F>(mut f: F, a: A) -> B
35 where
36 F: FnMut(A) -> B,
37 {
38 f(a)
39 }
40}
41
42impl Functor for UndetVec {
43 type Container<T> = Vec<T>;
44
45 #[inline(always)]
46 fn fmap<A, B, F>(f: F, fa: Self::Container<A>) -> Self::Container<B>
47 where
48 F: FnMut(A) -> B,
49 {
50 fa.into_iter().map(f).collect()
51 }
52}
53
54impl Functor for ZipVec {
55 type Container<T> = Vec<T>;
56
57 #[inline(always)]
58 fn fmap<A, B, F>(f: F, fa: Self::Container<A>) -> Self::Container<B>
59 where
60 F: FnMut(A) -> B,
61 {
62 fa.into_iter().map(f).collect()
63 }
64}
65
66impl Functor for OptionFunctor {
67 type Container<T> = Option<T>;
68
69 #[inline(always)]
70 fn fmap<A, B, F>(f: F, fa: Self::Container<A>) -> Self::Container<B>
71 where
72 F: FnMut(A) -> B,
73 {
74 fa.map(f)
75 }
76}
77
78impl<E> Functor for ResultFunctor<E> {
79 type Container<T> = Result<T, E>;
80
81 #[inline(always)]
82 fn fmap<A, B, F>(f: F, fa: Self::Container<A>) -> Self::Container<B>
83 where
84 F: FnMut(A) -> B,
85 {
86 fa.map(f)
87 }
88}
89
90impl Functor for V2 {
91 type Container<T> = (T, T);
92
93 #[inline(always)]
94 fn fmap<A, B, F>(mut f: F, (a1, a2): Self::Container<A>) -> Self::Container<B>
95 where
96 F: FnMut(A) -> B,
97 {
98 (f(a1), f(a2))
99 }
100}
101
102impl<const N: usize> Functor for ArrayFunctor<N> {
103 type Container<T> = [T; N];
104
105 #[inline(always)]
106 fn fmap<A, B, F>(f: F, fa: Self::Container<A>) -> Self::Container<B>
107 where
108 F: FnMut(A) -> B,
109 {
110 fa.map(f)
111 }
112}
113
114pub trait Pointed: Functor {
115 fn pure<T: Clone>(t: T) -> Self::Container<T>;
116}
117
118impl<G: Pointed> AsData<G> {
119 #[inline(always)]
120 pub fn pure<T: Clone>(t: T) -> G::Container<T> {
121 G::pure(t)
122 }
123}
124
125impl Pointed for Identity {
126 #[inline(always)]
127 fn pure<T: Clone>(t: T) -> T {
128 t
129 }
130}
131
132impl Pointed for OptionFunctor {
133 #[inline(always)]
134 fn pure<T: Clone>(t: T) -> Option<T> {
135 Some(t)
136 }
137}
138
139impl<E> Pointed for ResultFunctor<E> {
140 #[inline(always)]
141 fn pure<T: Clone>(t: T) -> Result<T, E> {
142 Ok(t)
143 }
144}
145
146impl Pointed for UndetVec {
147 #[inline(always)]
148 fn pure<T: Clone>(t: T) -> Vec<T> {
149 vec![t]
150 }
151}
152
153impl Pointed for V2 {
154 #[inline(always)]
155 fn pure<T: Clone>(t: T) -> (T, T) {
156 (t.clone(), t)
157 }
158}
159
160#[derive(Clone)]
161pub(crate) struct WrapArrayStruct<U>(pub(crate) U);
162impl<U> Debug for WrapArrayStruct<U> {
163 #[inline(always)]
164 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
165 f.write_str("<ELEMENT>")
166 }
167}
168
169#[inline(always)]
170pub(crate) fn unsafe_collect_array<const N: usize, I>(iter: I) -> [I::Item; N]
171where
172 I: Iterator,
173{
174 <[WrapArrayStruct<I::Item>; N]>::try_from(iter.map(WrapArrayStruct).collect::<Vec<_>>())
175 .unwrap()
176 .map(|WrapArrayStruct(t)| t)
177}
178
179impl<const N: usize> Pointed for ArrayFunctor<N> {
180 fn pure<T: Clone>(t: T) -> [T; N] {
181 unsafe_collect_array(itertools::repeat_n(t, N))
182 }
183}
184
185pub trait Apply: Functor {
186 fn zip_with<A, B, C, F>(
187 f: F,
188 fa: Self::Container<A>,
189 fb: Self::Container<B>,
190 ) -> Self::Container<C>
191 where
192 F: FnMut(A, B) -> C;
193
194 #[inline(always)]
195 fn ap<A, B, F>(ff: Self::Container<F>, fa: Self::Container<A>) -> Self::Container<B>
196 where
197 F: FnOnce(A) -> B,
198 {
199 Self::zip_with(|f, a| f(a), ff, fa)
200 }
201}
202
203impl<G: Apply> AsData<G> {
204 #[inline(always)]
205 pub fn zip_with<A, B, C, F>(f: F, fa: G::Container<A>, fb: G::Container<B>) -> G::Container<C>
206 where
207 F: FnMut(A, B) -> C,
208 {
209 G::zip_with(f, fa, fb)
210 }
211
212 #[inline(always)]
213 pub fn ap<A, B, F>(ff: G::Container<F>, fa: G::Container<A>) -> G::Container<B>
214 where
215 F: FnOnce(A) -> B,
216 {
217 G::ap(ff, fa)
218 }
219}
220
221impl Apply for Identity {
222 #[inline(always)]
223 fn zip_with<A, B, C, F>(mut f: F, a: A, b: B) -> C
224 where
225 F: FnMut(A, B) -> C,
226 {
227 f(a, b)
228 }
229}
230
231impl Apply for OptionFunctor {
232 #[inline(always)]
233 fn zip_with<A, B, C, F>(
234 mut f: F,
235 fa: Self::Container<A>,
236 fb: Self::Container<B>,
237 ) -> Self::Container<C>
238 where
239 F: FnMut(A, B) -> C,
240 {
241 fa.zip(fb).map(|(a, b)| f(a, b))
242 }
243}
244
245impl<E> Apply for ResultFunctor<E> {
246 #[inline(always)]
247 fn zip_with<A, B, C, F>(
248 mut f: F,
249 fa: Self::Container<A>,
250 fb: Self::Container<B>,
251 ) -> Self::Container<C>
252 where
253 F: FnMut(A, B) -> C,
254 {
255 fa.and_then(|a| fb.map(|b| f(a, b)))
256 }
257}
258
259impl Apply for ZipVec {
260 #[inline(always)]
261 fn zip_with<A, B, C, F>(
262 mut f: F,
263 fa: Self::Container<A>,
264 fb: Self::Container<B>,
265 ) -> Self::Container<C>
266 where
267 F: FnMut(A, B) -> C,
268 {
269 fa.into_iter().zip(fb).map(|(a, b)| f(a, b)).collect()
270 }
271}
272
273impl Apply for V2 {
274 #[inline(always)]
275 fn zip_with<A, B, C, F>(
276 mut f: F,
277 fa: Self::Container<A>,
278 fb: Self::Container<B>,
279 ) -> Self::Container<C>
280 where
281 F: FnMut(A, B) -> C,
282 {
283 (f(fa.0, fb.0), f(fa.1, fb.1))
284 }
285}
286
287impl<const N: usize> Apply for ArrayFunctor<N> {
288 #[inline(always)]
289 fn zip_with<A, B, C, F>(
290 mut f: F,
291 fa: Self::Container<A>,
292 fb: Self::Container<B>,
293 ) -> Self::Container<C>
294 where
295 F: FnMut(A, B) -> C,
296 {
297 unsafe_collect_array(fa.into_iter().zip(fb).map(|(a, b)| f(a, b)))
298 }
299}
300
301pub trait Alternative: Apply + Pointed {
302 fn empty<T>() -> Self::Container<T>;
303 fn choice<T>(a: Self::Container<T>, b: Self::Container<T>) -> Self::Container<T>;
304
305 #[inline(always)]
306 fn guard(p: bool) -> Self::Container<()> {
307 if p {
308 Self::pure(())
309 } else {
310 Self::empty()
311 }
312 }
313}
314
315impl<G: Alternative> AsData<G> {
316 #[inline(always)]
317 pub fn empty<T>() -> G::Container<T> {
318 G::empty()
319 }
320
321 #[inline(always)]
322 pub fn choice<T>(a: G::Container<T>, b: G::Container<T>) -> G::Container<T> {
323 G::choice(a, b)
324 }
325
326 #[inline(always)]
327 pub fn guard(p: bool) -> G::Container<()> {
328 G::guard(p)
329 }
330}
331
332impl Alternative for OptionFunctor {
333 #[inline(always)]
334 fn empty<T>() -> Option<T> {
335 None
336 }
337
338 #[inline(always)]
339 fn choice<T>(a: Self::Container<T>, b: Self::Container<T>) -> Self::Container<T> {
340 a.or(b)
341 }
342}
343
344impl<E: Default> Alternative for ResultFunctor<E> {
345 #[inline(always)]
346 fn empty<T>() -> Result<T, E> {
347 Err(E::default())
348 }
349
350 #[inline(always)]
351 fn choice<T>(a: Self::Container<T>, b: Self::Container<T>) -> Self::Container<T> {
352 a.or(b)
353 }
354}