1#[fp_macros::document_module]
20mod inner {
21 use {
22 crate::{
23 classes::*,
24 kinds::*,
25 types::*,
26 },
27 fp_macros::*,
28 };
29
30 #[document_examples]
55 #[kind(type Of<'a, A: 'a, B: 'a>: 'a;)]
98 pub trait Bifoldable {
99 #[document_signature]
104 #[document_type_parameters(
106 "The lifetime of the values.",
107 "The brand of the cloneable function to use.",
108 "The type of the first-position elements.",
109 "The type of the second-position elements.",
110 "The type of the accumulator."
111 )]
112 #[document_parameters(
114 "The step function for first-position elements.",
115 "The step function for second-position elements.",
116 "The initial accumulator value.",
117 "The bifoldable structure to fold."
118 )]
119 #[document_returns("The final accumulator value after folding all elements.")]
121 #[document_examples]
122 fn bi_fold_right<'a, FnBrand: LiftFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
138 f: impl Fn(A, C) -> C + 'a,
139 g: impl Fn(B, C) -> C + 'a,
140 z: C,
141 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
142 ) -> C {
143 let f = <FnBrand as LiftFn>::new(move |(a, c)| f(a, c));
144 let g = <FnBrand as LiftFn>::new(move |(b, c)| g(b, c));
145 let endo = Self::bi_fold_map::<FnBrand, A, B, Endofunction<'a, FnBrand, C>>(
146 move |a: A| {
147 let f = f.clone();
148 Endofunction::<FnBrand, C>::new(<FnBrand as LiftFn>::new(move |c| {
149 f((a.clone(), c))
150 }))
151 },
152 move |b: B| {
153 let g = g.clone();
154 Endofunction::<FnBrand, C>::new(<FnBrand as LiftFn>::new(move |c| {
155 g((b.clone(), c))
156 }))
157 },
158 p,
159 );
160 endo.0(z)
161 }
162
163 #[document_signature]
168 #[document_type_parameters(
170 "The lifetime of the values.",
171 "The brand of the cloneable function to use.",
172 "The type of the first-position elements.",
173 "The type of the second-position elements.",
174 "The type of the accumulator."
175 )]
176 #[document_parameters(
178 "The step function for first-position elements.",
179 "The step function for second-position elements.",
180 "The initial accumulator value.",
181 "The bifoldable structure to fold."
182 )]
183 #[document_returns("The final accumulator value after folding all elements.")]
185 #[document_examples]
186 fn bi_fold_left<'a, FnBrand: LiftFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
202 f: impl Fn(C, A) -> C + 'a,
203 g: impl Fn(C, B) -> C + 'a,
204 z: C,
205 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
206 ) -> C {
207 let f = <FnBrand as LiftFn>::new(move |(c, a)| f(c, a));
208 let g = <FnBrand as LiftFn>::new(move |(c, b)| g(c, b));
209 let endo = Self::bi_fold_right::<FnBrand, A, B, Endofunction<'a, FnBrand, C>>(
210 move |a: A, k: Endofunction<'a, FnBrand, C>| {
211 let f = f.clone();
212 let current =
213 Endofunction::<FnBrand, C>::new(<FnBrand as LiftFn>::new(move |c| {
214 f((c, a.clone()))
215 }));
216 Semigroup::append(k, current)
217 },
218 move |b: B, k: Endofunction<'a, FnBrand, C>| {
219 let g = g.clone();
220 let current =
221 Endofunction::<FnBrand, C>::new(<FnBrand as LiftFn>::new(move |c| {
222 g((c, b.clone()))
223 }));
224 Semigroup::append(k, current)
225 },
226 Endofunction::<FnBrand, C>::empty(),
227 p,
228 );
229 endo.0(z)
230 }
231
232 #[document_signature]
238 #[document_type_parameters(
240 "The lifetime of the values.",
241 "The brand of the cloneable function to use.",
242 "The type of the first-position elements.",
243 "The type of the second-position elements.",
244 "The monoid type to fold into."
245 )]
246 #[document_parameters(
248 "The function mapping first-position elements to the monoid.",
249 "The function mapping second-position elements to the monoid.",
250 "The bifoldable structure to fold."
251 )]
252 #[document_returns("The combined monoid value.")]
254 #[document_examples]
255 fn bi_fold_map<'a, FnBrand: LiftFn + 'a, A: 'a + Clone, B: 'a + Clone, M>(
270 f: impl Fn(A) -> M + 'a,
271 g: impl Fn(B) -> M + 'a,
272 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
273 ) -> M
274 where
275 M: Monoid + 'a, {
276 Self::bi_fold_right::<FnBrand, A, B, M>(
277 move |a, m| M::append(f(a), m),
278 move |b, m| M::append(g(b), m),
279 M::empty(),
280 p,
281 )
282 }
283 }
284
285 #[document_signature]
289 #[document_type_parameters(
291 "The lifetime of the values.",
292 "The brand of the cloneable function to use.",
293 "The brand of the bifoldable structure.",
294 "The type of the first-position elements.",
295 "The type of the second-position elements.",
296 "The type of the accumulator."
297 )]
298 #[document_parameters(
300 "The step function for first-position elements.",
301 "The step function for second-position elements.",
302 "The initial accumulator value.",
303 "The bifoldable structure to fold."
304 )]
305 #[document_returns("The final accumulator value after folding all elements.")]
307 #[document_examples]
308 pub fn bi_fold_right<
324 'a,
325 FnBrand: LiftFn + 'a,
326 Brand: Bifoldable,
327 A: 'a + Clone,
328 B: 'a + Clone,
329 C: 'a,
330 >(
331 f: impl Fn(A, C) -> C + 'a,
332 g: impl Fn(B, C) -> C + 'a,
333 z: C,
334 p: Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
335 ) -> C {
336 Brand::bi_fold_right::<FnBrand, A, B, C>(f, g, z, p)
337 }
338
339 #[document_signature]
343 #[document_type_parameters(
345 "The lifetime of the values.",
346 "The brand of the cloneable function to use.",
347 "The brand of the bifoldable structure.",
348 "The type of the first-position elements.",
349 "The type of the second-position elements.",
350 "The type of the accumulator."
351 )]
352 #[document_parameters(
354 "The step function for first-position elements.",
355 "The step function for second-position elements.",
356 "The initial accumulator value.",
357 "The bifoldable structure to fold."
358 )]
359 #[document_returns("The final accumulator value after folding all elements.")]
361 #[document_examples]
362 pub fn bi_fold_left<
378 'a,
379 FnBrand: LiftFn + 'a,
380 Brand: Bifoldable,
381 A: 'a + Clone,
382 B: 'a + Clone,
383 C: 'a,
384 >(
385 f: impl Fn(C, A) -> C + 'a,
386 g: impl Fn(C, B) -> C + 'a,
387 z: C,
388 p: Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
389 ) -> C {
390 Brand::bi_fold_left::<FnBrand, A, B, C>(f, g, z, p)
391 }
392
393 #[document_signature]
397 #[document_type_parameters(
399 "The lifetime of the values.",
400 "The brand of the cloneable function to use.",
401 "The brand of the bifoldable structure.",
402 "The type of the first-position elements.",
403 "The type of the second-position elements.",
404 "The monoid type to fold into."
405 )]
406 #[document_parameters(
408 "The function mapping first-position elements to the monoid.",
409 "The function mapping second-position elements to the monoid.",
410 "The bifoldable structure to fold."
411 )]
412 #[document_returns("The combined monoid value.")]
414 #[document_examples]
415 pub fn bi_fold_map<
430 'a,
431 FnBrand: LiftFn + 'a,
432 Brand: Bifoldable,
433 A: 'a + Clone,
434 B: 'a + Clone,
435 M,
436 >(
437 f: impl Fn(A) -> M + 'a,
438 g: impl Fn(B) -> M + 'a,
439 p: Apply!(<Brand as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
440 ) -> M
441 where
442 M: Monoid + 'a, {
443 Brand::bi_fold_map::<FnBrand, A, B, M>(f, g, p)
444 }
445}
446
447pub use inner::*;