fp_library/types/step.rs
1use crate::{
2 Apply,
3 brands::{StepBrand, StepWithDoneBrand, StepWithLoopBrand},
4 classes::{
5 applicative::Applicative, apply_first::ApplyFirst, apply_second::ApplySecond,
6 bifunctor::Bifunctor, cloneable_fn::CloneableFn, foldable::Foldable, functor::Functor,
7 lift::Lift, monoid::Monoid, par_foldable::ParFoldable, pointed::Pointed,
8 semiapplicative::Semiapplicative, semimonad::Semimonad, send_cloneable_fn::SendCloneableFn,
9 traversable::Traversable,
10 },
11 impl_kind,
12 kinds::*,
13};
14
15/// Represents the result of a single step in a tail-recursive computation.
16///
17/// This type is fundamental to stack-safe recursion via `MonadRec`.
18///
19/// ### Type Parameters
20///
21/// * `A`: The "loop" type - when we return `Loop(a)`, we continue with `a`.
22/// * `B`: The "done" type - when we return `Done(b)`, we're finished.
23///
24/// ### Variants
25///
26/// * `Loop(A)`: Continue the loop with a new value.
27/// * `Done(B)`: Finish the computation with a final value.
28///
29/// ### Examples
30///
31/// ```
32/// use fp_library::types::*;
33///
34/// let loop_step: Step<i32, i32> = Step::Loop(10);
35/// let done_step: Step<i32, i32> = Step::Done(20);
36/// ```
37#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
38pub enum Step<A, B> {
39 /// Continue the loop with a new value
40 Loop(A),
41 /// Finish the computation with a final value
42 Done(B),
43}
44
45impl<A, B> Step<A, B> {
46 /// Returns `true` if this is a `Loop` variant.
47 ///
48 /// ### Type Signature
49 ///
50 /// `forall b a. Step a b -> bool`
51 ///
52 /// ### Returns
53 ///
54 /// `true` if the step is a loop, `false` otherwise.
55 ///
56 /// ### Examples
57 ///
58 /// ```
59 /// use fp_library::types::*;
60 ///
61 /// let step: Step<i32, i32> = Step::Loop(1);
62 /// assert!(step.is_loop());
63 /// ```
64 #[inline]
65 pub fn is_loop(&self) -> bool {
66 matches!(self, Step::Loop(_))
67 }
68
69 /// Returns `true` if this is a `Done` variant.
70 ///
71 /// ### Type Signature
72 ///
73 /// `forall b a. Step a b -> bool`
74 ///
75 /// ### Returns
76 ///
77 /// `true` if the step is done, `false` otherwise.
78 ///
79 /// ### Examples
80 ///
81 /// ```
82 /// use fp_library::types::*;
83 ///
84 /// let step: Step<i32, i32> = Step::Done(1);
85 /// assert!(step.is_done());
86 /// ```
87 #[inline]
88 pub fn is_done(&self) -> bool {
89 matches!(self, Step::Done(_))
90 }
91
92 /// Maps a function over the `Loop` variant.
93 ///
94 /// ### Type Signature
95 ///
96 /// `forall c b a. (a -> c, Step a b) -> Step c b`
97 ///
98 /// ### Type Parameters
99 ///
100 /// * `C`: The new loop type.
101 ///
102 /// ### Parameters
103 ///
104 /// * `f`: The function to apply to the loop value.
105 ///
106 /// ### Returns
107 ///
108 /// A new `Step` with the loop value transformed.
109 ///
110 /// ### Examples
111 ///
112 /// ```
113 /// use fp_library::types::*;
114 ///
115 /// let step: Step<i32, i32> = Step::Loop(1);
116 /// let mapped = step.map_loop(|x| x + 1);
117 /// assert_eq!(mapped, Step::Loop(2));
118 /// ```
119 pub fn map_loop<C>(
120 self,
121 f: impl FnOnce(A) -> C,
122 ) -> Step<C, B> {
123 match self {
124 Step::Loop(a) => Step::Loop(f(a)),
125 Step::Done(b) => Step::Done(b),
126 }
127 }
128
129 /// Maps a function over the `Done` variant.
130 ///
131 /// ### Type Signature
132 ///
133 /// `forall c b a. (b -> c, Step a b) -> Step a c`
134 ///
135 /// ### Type Parameters
136 ///
137 /// * `C`: The new done type.
138 ///
139 /// ### Parameters
140 ///
141 /// * `f`: The function to apply to the done value.
142 ///
143 /// ### Returns
144 ///
145 /// A new `Step` with the done value transformed.
146 ///
147 /// ### Examples
148 ///
149 /// ```
150 /// use fp_library::types::*;
151 ///
152 /// let step: Step<i32, i32> = Step::Done(1);
153 /// let mapped = step.map_done(|x| x + 1);
154 /// assert_eq!(mapped, Step::Done(2));
155 /// ```
156 pub fn map_done<C>(
157 self,
158 f: impl FnOnce(B) -> C,
159 ) -> Step<A, C> {
160 match self {
161 Step::Loop(a) => Step::Loop(a),
162 Step::Done(b) => Step::Done(f(b)),
163 }
164 }
165
166 /// Applies functions to both variants (bifunctor map).
167 ///
168 /// ### Type Signature
169 ///
170 /// `forall d c b a. (a -> c, b -> d, Step a b) -> Step c d`
171 ///
172 /// ### Type Parameters
173 ///
174 /// * `C`: The new loop type.
175 /// * `D`: The new done type.
176 ///
177 /// ### Parameters
178 ///
179 /// * `f`: The function to apply to the loop value.
180 /// * `g`: The function to apply to the done value.
181 ///
182 /// ### Returns
183 ///
184 /// A new `Step` with both values transformed.
185 ///
186 /// ### Examples
187 ///
188 /// ```
189 /// use fp_library::types::*;
190 ///
191 /// let step: Step<i32, i32> = Step::Loop(1);
192 /// let mapped = step.bimap(|x| x + 1, |x| x * 2);
193 /// assert_eq!(mapped, Step::Loop(2));
194 /// ```
195 pub fn bimap<C, D>(
196 self,
197 f: impl FnOnce(A) -> C,
198 g: impl FnOnce(B) -> D,
199 ) -> Step<C, D> {
200 match self {
201 Step::Loop(a) => Step::Loop(f(a)),
202 Step::Done(b) => Step::Done(g(b)),
203 }
204 }
205}
206
207impl_kind! {
208 for StepBrand {
209 type Of<A, B> = Step<A, B>;
210 }
211}
212
213impl_kind! {
214 for StepBrand {
215 type Of<'a, A: 'a, B: 'a>: 'a = Step<A, B>;
216 }
217}
218
219impl Bifunctor for StepBrand {
220 /// Maps functions over the values in the step.
221 ///
222 /// This method applies one function to the loop value and another to the done value.
223 ///
224 /// ### Type Signature
225 ///
226 /// `forall a b c d. Bifunctor Step => (a -> b, c -> d, Step a c) -> Step b d`
227 ///
228 /// ### Type Parameters
229 ///
230 /// * `A`: The type of the loop value.
231 /// * `B`: The type of the mapped loop value.
232 /// * `C`: The type of the done value.
233 /// * `D`: The type of the mapped done value.
234 /// * `F`: The type of the function to apply to the loop value.
235 /// * `G`: The type of the function to apply to the done value.
236 ///
237 /// ### Parameters
238 ///
239 /// * `f`: The function to apply to the loop value.
240 /// * `g`: The function to apply to the done value.
241 /// * `p`: The step to map over.
242 ///
243 /// ### Returns
244 ///
245 /// A new step containing the mapped values.
246 ///
247 /// ### Examples
248 ///
249 /// ```
250 /// use fp_library::{brands::*, classes::bifunctor::*, functions::*, types::*};
251 ///
252 /// let x = Step::Loop(1);
253 /// assert_eq!(bimap::<StepBrand, _, _, _, _, _, _>(|a| a + 1, |b: i32| b * 2, x), Step::Loop(2));
254 /// ```
255 fn bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a, F, G>(
256 f: F,
257 g: G,
258 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
259 ) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>)
260 where
261 F: Fn(A) -> B + 'a,
262 G: Fn(C) -> D + 'a,
263 {
264 p.bimap(f, g)
265 }
266}
267
268// StepWithLoopBrand<LoopType> (Functor over B - Done)
269
270impl_kind! {
271 impl<LoopType: 'static> for StepWithLoopBrand<LoopType> {
272 type Of<'a, B: 'a>: 'a = Step<LoopType, B>;
273 }
274}
275
276impl<LoopType: 'static> Functor for StepWithLoopBrand<LoopType> {
277 /// Maps a function over the done value in the step.
278 ///
279 /// This method applies a function to the done value inside the step, producing a new step with the transformed done value. The loop value remains unchanged.
280 ///
281 /// ### Type Signature
282 ///
283 /// `forall t b a. Functor (StepWithLoop t) => (a -> b, Step t a) -> Step t b`
284 ///
285 /// ### Type Parameters
286 ///
287 /// * `B`: The type of the result of applying the function.
288 /// * `A`: The type of the done value.
289 /// * `F`: The type of the function to apply.
290 ///
291 /// ### Parameters
292 ///
293 /// * `f`: The function to apply to the done value.
294 /// * `fa`: The step to map over.
295 ///
296 /// ### Returns
297 ///
298 /// A new step containing the result of applying the function to the done value.
299 ///
300 /// ### Examples
301 ///
302 /// ```
303 /// use fp_library::{brands::*, functions::*, types::*};
304 ///
305 /// assert_eq!(map::<StepWithLoopBrand<i32>, _, _, _>(|x: i32| x * 2, Step::<i32, i32>::Done(5)), Step::Done(10));
306 /// ```
307 fn map<'a, B: 'a, A: 'a, F>(
308 f: F,
309 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
310 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
311 where
312 F: Fn(A) -> B + 'a,
313 {
314 fa.map_done(f)
315 }
316}
317
318impl<LoopType: Clone + 'static> Lift for StepWithLoopBrand<LoopType> {
319 /// Lifts a binary function into the step context.
320 ///
321 /// This method lifts a binary function to operate on values within the step context.
322 ///
323 /// ### Type Signature
324 ///
325 /// `forall t c a b. Lift (StepWithLoop t) => ((a, b) -> c, Step t a, Step t b) -> Step t c`
326 ///
327 /// ### Type Parameters
328 ///
329 /// * `C`: The type of the result.
330 /// * `A`: The type of the first value.
331 /// * `B`: The type of the second value.
332 /// * `F`: The type of the binary function.
333 ///
334 /// ### Parameters
335 ///
336 /// * `f`: The binary function to apply.
337 /// * `fa`: The first step.
338 /// * `fb`: The second step.
339 ///
340 /// ### Returns
341 ///
342 /// `Done(f(a, b))` if both steps are `Done`, otherwise the first loop encountered.
343 ///
344 /// ### Examples
345 ///
346 /// ```
347 /// use fp_library::{brands::*, functions::*, types::*};
348 ///
349 /// assert_eq!(
350 /// lift2::<StepWithLoopBrand<()>, _, _, _, _>(|x: i32, y: i32| x + y, Step::Done(1), Step::Done(2)),
351 /// Step::Done(3)
352 /// );
353 /// assert_eq!(
354 /// lift2::<StepWithLoopBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Step::Done(1), Step::Loop(2)),
355 /// Step::Loop(2)
356 /// );
357 /// ```
358 fn lift2<'a, C, A, B, F>(
359 f: F,
360 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
361 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
362 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
363 where
364 F: Fn(A, B) -> C + 'a,
365 A: Clone + 'a,
366 B: Clone + 'a,
367 C: 'a,
368 {
369 match (fa, fb) {
370 (Step::Done(a), Step::Done(b)) => Step::Done(f(a, b)),
371 (Step::Loop(e), _) => Step::Loop(e),
372 (_, Step::Loop(e)) => Step::Loop(e),
373 }
374 }
375}
376
377impl<LoopType: 'static> Pointed for StepWithLoopBrand<LoopType> {
378 /// Wraps a value in a step.
379 ///
380 /// This method wraps a value in the `Done` variant of a `Step`.
381 ///
382 /// ### Type Signature
383 ///
384 /// `forall t a. Pointed (StepWithLoop t) => a -> Step t a`
385 ///
386 /// ### Type Parameters
387 ///
388 /// * `A`: The type of the value to wrap.
389 ///
390 /// ### Parameters
391 ///
392 /// * `a`: The value to wrap.
393 ///
394 /// ### Returns
395 ///
396 /// `Done(a)`.
397 ///
398 /// ### Examples
399 ///
400 /// ```
401 /// use fp_library::{brands::*, functions::*, types::*};
402 ///
403 /// assert_eq!(pure::<StepWithLoopBrand<()>, _>(5), Step::Done(5));
404 /// ```
405 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
406 Step::Done(a)
407 }
408}
409
410impl<LoopType: Clone + 'static> ApplyFirst for StepWithLoopBrand<LoopType> {}
411impl<LoopType: Clone + 'static> ApplySecond for StepWithLoopBrand<LoopType> {}
412
413impl<LoopType: Clone + 'static> Semiapplicative for StepWithLoopBrand<LoopType> {
414 /// Applies a wrapped function to a wrapped value.
415 ///
416 /// This method applies a function wrapped in a step to a value wrapped in a step.
417 ///
418 /// ### Type Signature
419 ///
420 /// `forall fn_brand t b a. Semiapplicative (StepWithLoop t) => (Step t (fn_brand a b), Step t a) -> Step t b`
421 ///
422 /// ### Type Parameters
423 ///
424 /// * `FnBrand`: The brand of the cloneable function wrapper.
425 /// * `B`: The type of the output value.
426 /// * `A`: The type of the input value.
427 ///
428 /// ### Parameters
429 ///
430 /// * `ff`: The step containing the function.
431 /// * `fa`: The step containing the value.
432 ///
433 /// ### Returns
434 ///
435 /// `Done(f(a))` if both are `Done`, otherwise the first loop encountered.
436 ///
437 /// ### Examples
438 ///
439 /// ```
440 /// use fp_library::{brands::*, classes::*, functions::*, types::*};
441 ///
442 /// let f: Step<_, _> = Step::Done(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
443 /// assert_eq!(apply::<RcFnBrand, StepWithLoopBrand<()>, _, _>(f, Step::Done(5)), Step::Done(10));
444 /// ```
445 fn apply<'a, FnBrand: 'a + CloneableFn, B: 'a, A: 'a + Clone>(
446 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
447 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
448 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
449 match (ff, fa) {
450 (Step::Done(f), Step::Done(a)) => Step::Done(f(a)),
451 (Step::Loop(e), _) => Step::Loop(e),
452 (_, Step::Loop(e)) => Step::Loop(e),
453 }
454 }
455}
456
457impl<LoopType: Clone + 'static> Semimonad for StepWithLoopBrand<LoopType> {
458 /// Chains step computations.
459 ///
460 /// This method chains two computations, where the second computation depends on the result of the first.
461 ///
462 /// ### Type Signature
463 ///
464 /// `forall t b a. Semimonad (StepWithLoop t) => (Step t a, a -> Step t b) -> Step t b`
465 ///
466 /// ### Type Parameters
467 ///
468 /// * `B`: The type of the result of the second computation.
469 /// * `A`: The type of the result of the first computation.
470 /// * `F`: The type of the function to apply.
471 ///
472 /// ### Parameters
473 ///
474 /// * `ma`: The first step.
475 /// * `f`: The function to apply to the value inside the step.
476 ///
477 /// ### Returns
478 ///
479 /// The result of applying `f` to the value if `ma` is `Done`, otherwise the original loop.
480 ///
481 /// ### Examples
482 ///
483 /// ```
484 /// use fp_library::{brands::*, functions::*, types::*};
485 ///
486 /// assert_eq!(
487 /// bind::<StepWithLoopBrand<()>, _, _, _>(Step::Done(5), |x| Step::Done(x * 2)),
488 /// Step::Done(10)
489 /// );
490 /// ```
491 fn bind<'a, B: 'a, A: 'a, F>(
492 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
493 f: F,
494 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
495 where
496 F: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
497 {
498 match ma {
499 Step::Done(a) => f(a),
500 Step::Loop(e) => Step::Loop(e),
501 }
502 }
503}
504
505impl<LoopType: 'static> Foldable for StepWithLoopBrand<LoopType> {
506 /// Folds the step from the right.
507 ///
508 /// This method performs a right-associative fold of the step.
509 ///
510 /// ### Type Signature
511 ///
512 /// `forall t b a. Foldable (StepWithLoop t) => ((a, b) -> b, b, Step t a) -> b`
513 ///
514 /// ### Type Parameters
515 ///
516 /// * `FnBrand`: The brand of the cloneable function to use.
517 /// * `B`: The type of the accumulator.
518 /// * `A`: The type of the elements in the structure.
519 /// * `F`: The type of the folding function.
520 ///
521 /// ### Parameters
522 ///
523 /// * `func`: The folding function.
524 /// * `initial`: The initial value.
525 /// * `fa`: The step to fold.
526 ///
527 /// ### Returns
528 ///
529 /// `func(a, initial)` if `fa` is `Done(a)`, otherwise `initial`.
530 ///
531 /// ### Examples
532 ///
533 /// ```
534 /// use fp_library::{brands::*, functions::*, types::*};
535 ///
536 /// assert_eq!(fold_right::<RcFnBrand, StepWithLoopBrand<()>, _, _, _>(|x, acc| x + acc, 0, Step::Done(5)), 5);
537 /// assert_eq!(fold_right::<RcFnBrand, StepWithLoopBrand<i32>, _, _, _>(|x: i32, acc| x + acc, 0, Step::Loop(1)), 0);
538 /// ```
539 fn fold_right<'a, FnBrand, B: 'a, A: 'a, F>(
540 func: F,
541 initial: B,
542 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
543 ) -> B
544 where
545 F: Fn(A, B) -> B + 'a,
546 FnBrand: CloneableFn + 'a,
547 {
548 match fa {
549 Step::Done(a) => func(a, initial),
550 Step::Loop(_) => initial,
551 }
552 }
553
554 /// Folds the step from the left.
555 ///
556 /// This method performs a left-associative fold of the step.
557 ///
558 /// ### Type Signature
559 ///
560 /// `forall t b a. Foldable (StepWithLoop t) => ((b, a) -> b, b, Step t a) -> b`
561 ///
562 /// ### Type Parameters
563 ///
564 /// * `FnBrand`: The brand of the cloneable function to use.
565 /// * `B`: The type of the accumulator.
566 /// * `A`: The type of the elements in the structure.
567 /// * `F`: The type of the folding function.
568 ///
569 /// ### Parameters
570 ///
571 /// * `func`: The folding function.
572 /// * `initial`: The initial value.
573 /// * `fa`: The step to fold.
574 ///
575 /// ### Returns
576 ///
577 /// `func(initial, a)` if `fa` is `Done(a)`, otherwise `initial`.
578 ///
579 /// ### Examples
580 ///
581 /// ```
582 /// use fp_library::{brands::*, functions::*, types::*};
583 ///
584 /// assert_eq!(fold_left::<RcFnBrand, StepWithLoopBrand<()>, _, _, _>(|acc, x| acc + x, 0, Step::Done(5)), 5);
585 /// assert_eq!(fold_left::<RcFnBrand, StepWithLoopBrand<i32>, _, _, _>(|acc, x: i32| acc + x, 0, Step::Loop(1)), 0);
586 /// ```
587 fn fold_left<'a, FnBrand, B: 'a, A: 'a, F>(
588 func: F,
589 initial: B,
590 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
591 ) -> B
592 where
593 F: Fn(B, A) -> B + 'a,
594 FnBrand: CloneableFn + 'a,
595 {
596 match fa {
597 Step::Done(a) => func(initial, a),
598 Step::Loop(_) => initial,
599 }
600 }
601
602 /// Maps the value to a monoid and returns it.
603 ///
604 /// This method maps the element of the step to a monoid and then returns it.
605 ///
606 /// ### Type Signature
607 ///
608 /// `forall t m a. (Foldable (StepWithLoop t), Monoid m) => ((a) -> m, Step t a) -> m`
609 ///
610 /// ### Type Parameters
611 ///
612 /// * `FnBrand`: The brand of the cloneable function to use.
613 /// * `M`: The type of the monoid.
614 /// * `A`: The type of the elements in the structure.
615 /// * `F`: The type of the mapping function.
616 ///
617 /// ### Parameters
618 ///
619 /// * `func`: The mapping function.
620 /// * `fa`: The step to fold.
621 ///
622 /// ### Returns
623 ///
624 /// `func(a)` if `fa` is `Done(a)`, otherwise `M::empty()`.
625 ///
626 /// ### Examples
627 ///
628 /// ```
629 /// use fp_library::{brands::*, functions::*, types::*};
630 ///
631 /// assert_eq!(
632 /// fold_map::<RcFnBrand, StepWithLoopBrand<()>, _, _, _>(|x: i32| x.to_string(), Step::Done(5)),
633 /// "5".to_string()
634 /// );
635 /// assert_eq!(
636 /// fold_map::<RcFnBrand, StepWithLoopBrand<i32>, _, _, _>(|x: i32| x.to_string(), Step::Loop(1)),
637 /// "".to_string()
638 /// );
639 /// ```
640 fn fold_map<'a, FnBrand, M, A: 'a, F>(
641 func: F,
642 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
643 ) -> M
644 where
645 M: Monoid + 'a,
646 F: Fn(A) -> M + 'a,
647 FnBrand: CloneableFn + 'a,
648 {
649 match fa {
650 Step::Done(a) => func(a),
651 Step::Loop(_) => M::empty(),
652 }
653 }
654}
655
656impl<LoopType: Clone + 'static> Traversable for StepWithLoopBrand<LoopType> {
657 /// Traverses the step with an applicative function.
658 ///
659 /// This method maps the element of the step to a computation, evaluates it, and combines the result into an applicative context.
660 ///
661 /// ### Type Signature
662 ///
663 /// `forall t f b a. (Traversable (StepWithLoop t), Applicative f) => (a -> f b, Step t a) -> f (Step t b)`
664 ///
665 /// ### Type Parameters
666 ///
667 /// * `F`: The applicative context.
668 /// * `B`: The type of the elements in the resulting traversable structure.
669 /// * `A`: The type of the elements in the traversable structure.
670 /// * `Func`: The type of the function to apply.
671 ///
672 /// ### Parameters
673 ///
674 /// * `func`: The function to apply.
675 /// * `ta`: The step to traverse.
676 ///
677 /// ### Returns
678 ///
679 /// The step wrapped in the applicative context.
680 ///
681 /// ### Examples
682 ///
683 /// ```
684 /// use fp_library::{brands::*, functions::*, types::*};
685 ///
686 /// assert_eq!(
687 /// traverse::<StepWithLoopBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Step::Done(5)),
688 /// Some(Step::Done(10))
689 /// );
690 /// assert_eq!(
691 /// traverse::<StepWithLoopBrand<i32>, OptionBrand, _, _, _>(|x: i32| Some(x * 2), Step::Loop(1)),
692 /// Some(Step::Loop(1))
693 /// );
694 /// ```
695 fn traverse<'a, F: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
696 func: Func,
697 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
698 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
699 where
700 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
701 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
702 {
703 match ta {
704 Step::Done(a) => F::map(|b| Step::Done(b), func(a)),
705 Step::Loop(e) => F::pure(Step::Loop(e)),
706 }
707 }
708
709 /// Sequences a step of applicative.
710 ///
711 /// This method evaluates the computation inside the step and accumulates the result into an applicative context.
712 ///
713 /// ### Type Signature
714 ///
715 /// `forall t f a. (Traversable (StepWithLoop t), Applicative f) => (Step t (f a)) -> f (Step t a)`
716 ///
717 /// ### Type Parameters
718 ///
719 /// * `F`: The applicative context.
720 /// * `A`: The type of the elements in the traversable structure.
721 ///
722 /// ### Parameters
723 ///
724 /// * `ta`: The step containing the applicative value.
725 ///
726 /// ### Returns
727 ///
728 /// The step wrapped in the applicative context.
729 ///
730 /// ### Examples
731 ///
732 /// ```
733 /// use fp_library::{brands::*, functions::*, types::*};
734 ///
735 /// assert_eq!(
736 /// sequence::<StepWithLoopBrand<()>, OptionBrand, _>(Step::Done(Some(5))),
737 /// Some(Step::Done(5))
738 /// );
739 /// assert_eq!(
740 /// sequence::<StepWithLoopBrand<i32>, OptionBrand, i32>(Step::Loop::<i32, Option<i32>>(1)),
741 /// Some(Step::Loop::<i32, i32>(1))
742 /// );
743 /// ```
744 fn sequence<'a, F: Applicative, A: 'a + Clone>(
745 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
746 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
747 where
748 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
749 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
750 {
751 match ta {
752 Step::Done(fa) => F::map(|a| Step::Done(a), fa),
753 Step::Loop(e) => F::pure(Step::Loop(e)),
754 }
755 }
756}
757
758impl<LoopType: 'static, FnBrand: SendCloneableFn> ParFoldable<FnBrand>
759 for StepWithLoopBrand<LoopType>
760{
761 /// Maps the value to a monoid and returns it, or returns empty, in parallel.
762 ///
763 /// This method maps the element of the step to a monoid and then returns it. The mapping operation may be executed in parallel.
764 ///
765 /// ### Type Signature
766 ///
767 /// `forall fn_brand t m a. (ParFoldable (StepWithLoop t), Monoid m, Send m, Sync m) => (fn_brand a m, Step t a) -> m`
768 ///
769 /// ### Type Parameters
770 ///
771 /// * `FnBrand`: The brand of thread-safe function to use.
772 /// * `M`: The monoid type (must be `Send + Sync`).
773 /// * `A`: The element type (must be `Send + Sync`).
774 ///
775 /// ### Parameters
776 ///
777 /// * `func`: The thread-safe function to map each element to a monoid.
778 /// * `fa`: The step to fold.
779 ///
780 /// ### Returns
781 ///
782 /// The combined monoid value.
783 ///
784 /// ### Examples
785 ///
786 /// ```
787 /// use fp_library::{brands::*, classes::*, functions::*, types::*};
788 ///
789 /// let x: Step<i32, i32> = Step::Done(5);
790 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
791 /// assert_eq!(par_fold_map::<ArcFnBrand, StepWithLoopBrand<i32>, _, _>(f.clone(), x), "5".to_string());
792 ///
793 /// let x_loop: Step<i32, i32> = Step::Loop(1);
794 /// assert_eq!(par_fold_map::<ArcFnBrand, StepWithLoopBrand<i32>, _, _>(f, x_loop), "".to_string());
795 /// ```
796 fn par_fold_map<'a, M, A>(
797 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
798 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
799 ) -> M
800 where
801 A: 'a + Clone + Send + Sync,
802 M: Monoid + Send + Sync + 'a,
803 {
804 match fa {
805 Step::Done(a) => func(a),
806 Step::Loop(_) => M::empty(),
807 }
808 }
809
810 /// Folds the step from the right in parallel.
811 ///
812 /// This method folds the step by applying a function from right to left, potentially in parallel.
813 ///
814 /// ### Type Signature
815 ///
816 /// `forall fn_brand t b a. ParFoldable (StepWithLoop t) => (fn_brand (a, b) b, b, Step t a) -> b`
817 ///
818 /// ### Type Parameters
819 ///
820 /// * `FnBrand`: The brand of thread-safe function to use.
821 /// * `B`: The accumulator type (must be `Send + Sync`).
822 /// * `A`: The element type (must be `Send + Sync`).
823 ///
824 /// ### Parameters
825 ///
826 /// * `func`: The thread-safe function to apply to each element and the accumulator.
827 /// * `initial`: The initial value.
828 /// * `fa`: The step to fold.
829 ///
830 /// ### Returns
831 ///
832 /// The final accumulator value.
833 ///
834 /// ### Examples
835 ///
836 /// ```
837 /// use fp_library::{brands::*, classes::*, functions::*, types::*};
838 ///
839 /// let x: Step<i32, i32> = Step::Done(5);
840 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
841 /// assert_eq!(par_fold_right::<ArcFnBrand, StepWithLoopBrand<i32>, _, _>(f.clone(), 10, x), 15);
842 ///
843 /// let x_loop: Step<i32, i32> = Step::Loop(1);
844 /// assert_eq!(par_fold_right::<ArcFnBrand, StepWithLoopBrand<i32>, _, _>(f, 10, x_loop), 10);
845 /// ```
846 fn par_fold_right<'a, B, A>(
847 func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
848 initial: B,
849 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
850 ) -> B
851 where
852 A: 'a + Clone + Send + Sync,
853 B: Send + Sync + 'a,
854 {
855 match fa {
856 Step::Done(a) => func((a, initial)),
857 Step::Loop(_) => initial,
858 }
859 }
860}
861
862// StepWithDoneBrand<DoneType> (Functor over A - Loop)
863
864impl_kind! {
865 impl<DoneType: 'static> for StepWithDoneBrand<DoneType> {
866 type Of<'a, A: 'a>: 'a = Step<A, DoneType>;
867 }
868}
869
870impl<DoneType: 'static> Functor for StepWithDoneBrand<DoneType> {
871 /// Maps a function over the loop value in the step.
872 ///
873 /// This method applies a function to the loop value inside the step, producing a new step with the transformed loop value. The done value remains unchanged.
874 ///
875 /// ### Type Signature
876 ///
877 /// `forall t b a. Functor (StepWithDone t) => (a -> b, Step a t) -> Step b t`
878 ///
879 /// ### Type Parameters
880 ///
881 /// * `B`: The type of the result of applying the function.
882 /// * `A`: The type of the loop value.
883 /// * `F`: The type of the function to apply.
884 ///
885 /// ### Parameters
886 ///
887 /// * `f`: The function to apply to the loop value.
888 /// * `fa`: The step to map over.
889 ///
890 /// ### Returns
891 ///
892 /// A new step containing the result of applying the function to the loop value.
893 ///
894 /// ### Examples
895 ///
896 /// ```
897 /// use fp_library::{brands::*, functions::*, types::*};
898 ///
899 /// assert_eq!(map::<StepWithDoneBrand<i32>, _, _, _>(|x: i32| x * 2, Step::<i32, i32>::Loop(5)), Step::Loop(10));
900 /// ```
901 fn map<'a, B: 'a, A: 'a, F>(
902 f: F,
903 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
904 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
905 where
906 F: Fn(A) -> B + 'a,
907 {
908 fa.map_loop(f)
909 }
910}
911
912impl<DoneType: Clone + 'static> Lift for StepWithDoneBrand<DoneType> {
913 /// Lifts a binary function into the step context (over loop).
914 ///
915 /// This method lifts a binary function to operate on loop values within the step context.
916 ///
917 /// ### Type Signature
918 ///
919 /// `forall t c a b. Lift (StepWithDone t) => ((a, b) -> c, Step a t, Step b t) -> Step c t`
920 ///
921 /// ### Type Parameters
922 ///
923 /// * `C`: The type of the result loop value.
924 /// * `A`: The type of the first loop value.
925 /// * `B`: The type of the second loop value.
926 /// * `F`: The type of the binary function.
927 ///
928 /// ### Parameters
929 ///
930 /// * `f`: The binary function to apply to the loops.
931 /// * `fa`: The first step.
932 /// * `fb`: The second step.
933 ///
934 /// ### Returns
935 ///
936 /// `Loop(f(a, b))` if both steps are `Loop`, otherwise the first done encountered.
937 ///
938 /// ### Examples
939 ///
940 /// ```
941 /// use fp_library::{brands::*, functions::*, types::*};
942 ///
943 /// assert_eq!(
944 /// lift2::<StepWithDoneBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Step::Loop(1), Step::Loop(2)),
945 /// Step::Loop(3)
946 /// );
947 /// assert_eq!(
948 /// lift2::<StepWithDoneBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Step::Loop(1), Step::Done(2)),
949 /// Step::Done(2)
950 /// );
951 /// ```
952 fn lift2<'a, C, A, B, F>(
953 f: F,
954 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
955 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
956 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
957 where
958 F: Fn(A, B) -> C + 'a,
959 A: Clone + 'a,
960 B: Clone + 'a,
961 C: 'a,
962 {
963 match (fa, fb) {
964 (Step::Loop(a), Step::Loop(b)) => Step::Loop(f(a, b)),
965 (Step::Done(t), _) => Step::Done(t),
966 (_, Step::Done(t)) => Step::Done(t),
967 }
968 }
969}
970
971impl<DoneType: 'static> Pointed for StepWithDoneBrand<DoneType> {
972 /// Wraps a value in a step (as loop).
973 ///
974 /// This method wraps a value in the `Loop` variant of a `Step`.
975 ///
976 /// ### Type Signature
977 ///
978 /// `forall t a. Pointed (StepWithDone t) => a -> Step a t`
979 ///
980 /// ### Type Parameters
981 ///
982 /// * `A`: The type of the value to wrap.
983 ///
984 /// ### Parameters
985 ///
986 /// * `a`: The value to wrap.
987 ///
988 /// ### Returns
989 ///
990 /// `Loop(a)`.
991 ///
992 /// ### Examples
993 ///
994 /// ```
995 /// use fp_library::{brands::*, functions::*, types::*};
996 ///
997 /// assert_eq!(pure::<StepWithDoneBrand<()>, _>(5), Step::Loop(5));
998 /// ```
999 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
1000 Step::Loop(a)
1001 }
1002}
1003
1004impl<DoneType: Clone + 'static> ApplyFirst for StepWithDoneBrand<DoneType> {}
1005impl<DoneType: Clone + 'static> ApplySecond for StepWithDoneBrand<DoneType> {}
1006
1007impl<DoneType: Clone + 'static> Semiapplicative for StepWithDoneBrand<DoneType> {
1008 /// Applies a wrapped function to a wrapped value (over loop).
1009 ///
1010 /// This method applies a function wrapped in a step (as loop) to a value wrapped in a step (as loop).
1011 ///
1012 /// ### Type Signature
1013 ///
1014 /// `forall fn_brand t b a. Semiapplicative (StepWithDone t) => (Step (fn_brand a b) t, Step a t) -> Step b t`
1015 ///
1016 /// ### Type Parameters
1017 ///
1018 /// * `FnBrand`: The brand of the cloneable function wrapper.
1019 /// * `B`: The type of the output value.
1020 /// * `A`: The type of the input value.
1021 ///
1022 /// ### Parameters
1023 ///
1024 /// * `ff`: The step containing the function (in Loop).
1025 /// * `fa`: The step containing the value (in Loop).
1026 ///
1027 /// ### Returns
1028 ///
1029 /// `Loop(f(a))` if both are `Loop`, otherwise the first done encountered.
1030 ///
1031 /// ### Examples
1032 ///
1033 /// ```
1034 /// use fp_library::{brands::*, classes::*, functions::*, types::*};
1035 ///
1036 /// let f: Step<_, ()> = Step::Loop(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
1037 /// assert_eq!(apply::<RcFnBrand, StepWithDoneBrand<()>, _, _>(f, Step::Loop(5)), Step::Loop(10));
1038 /// ```
1039 fn apply<'a, FnBrand: 'a + CloneableFn, B: 'a, A: 'a + Clone>(
1040 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
1041 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1042 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1043 match (ff, fa) {
1044 (Step::Loop(f), Step::Loop(a)) => Step::Loop(f(a)),
1045 (Step::Done(t), _) => Step::Done(t),
1046 (_, Step::Done(t)) => Step::Done(t),
1047 }
1048 }
1049}
1050
1051impl<DoneType: Clone + 'static> Semimonad for StepWithDoneBrand<DoneType> {
1052 /// Chains step computations (over loop).
1053 ///
1054 /// This method chains two computations, where the second computation depends on the result of the first (over loop).
1055 ///
1056 /// ### Type Signature
1057 ///
1058 /// `forall t b a. Semimonad (StepWithDone t) => (Step a t, a -> Step b t) -> Step b t`
1059 ///
1060 /// ### Type Parameters
1061 ///
1062 /// * `B`: The type of the result of the second computation.
1063 /// * `A`: The type of the result of the first computation.
1064 /// * `F`: The type of the function to apply.
1065 ///
1066 /// ### Parameters
1067 ///
1068 /// * `ma`: The first step.
1069 /// * `f`: The function to apply to the loop value.
1070 ///
1071 /// ### Returns
1072 ///
1073 /// The result of applying `f` to the loop if `ma` is `Loop`, otherwise the original done.
1074 ///
1075 /// ### Examples
1076 ///
1077 /// ```
1078 /// use fp_library::{brands::*, functions::*, types::*};
1079 ///
1080 /// assert_eq!(
1081 /// bind::<StepWithDoneBrand<()>, _, _, _>(Step::Loop(5), |x| Step::Loop(x * 2)),
1082 /// Step::Loop(10)
1083 /// );
1084 /// ```
1085 fn bind<'a, B: 'a, A: 'a, F>(
1086 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1087 f: F,
1088 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
1089 where
1090 F: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1091 {
1092 match ma {
1093 Step::Done(t) => Step::Done(t),
1094 Step::Loop(e) => f(e),
1095 }
1096 }
1097}
1098
1099impl<DoneType: 'static> Foldable for StepWithDoneBrand<DoneType> {
1100 /// Folds the step from the right (over loop).
1101 ///
1102 /// This method performs a right-associative fold of the step (over loop).
1103 ///
1104 /// ### Type Signature
1105 ///
1106 /// `forall t b a. Foldable (StepWithDone t) => ((a, b) -> b, b, Step a t) -> b`
1107 ///
1108 /// ### Type Parameters
1109 ///
1110 /// * `FnBrand`: The brand of the cloneable function to use.
1111 /// * `B`: The type of the accumulator.
1112 /// * `A`: The type of the elements in the structure.
1113 /// * `F`: The type of the folding function.
1114 ///
1115 /// ### Parameters
1116 ///
1117 /// * `func`: The folding function.
1118 /// * `initial`: The initial value.
1119 /// * `fa`: The step to fold.
1120 ///
1121 /// ### Returns
1122 ///
1123 /// `func(a, initial)` if `fa` is `Loop(a)`, otherwise `initial`.
1124 ///
1125 /// ### Examples
1126 ///
1127 /// ```
1128 /// use fp_library::{brands::*, functions::*, types::*};
1129 ///
1130 /// assert_eq!(fold_right::<RcFnBrand, StepWithDoneBrand<i32>, _, _, _>(|x: i32, acc| x + acc, 0, Step::Loop(1)), 1);
1131 /// assert_eq!(fold_right::<RcFnBrand, StepWithDoneBrand<()>, _, _, _>(|x: i32, acc| x + acc, 0, Step::Done(())), 0);
1132 /// ```
1133 fn fold_right<'a, FnBrand, B: 'a, A: 'a, F>(
1134 func: F,
1135 initial: B,
1136 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1137 ) -> B
1138 where
1139 F: Fn(A, B) -> B + 'a,
1140 FnBrand: CloneableFn + 'a,
1141 {
1142 match fa {
1143 Step::Loop(e) => func(e, initial),
1144 Step::Done(_) => initial,
1145 }
1146 }
1147
1148 /// Folds the step from the left (over loop).
1149 ///
1150 /// This method performs a left-associative fold of the step (over loop).
1151 ///
1152 /// ### Type Signature
1153 ///
1154 /// `forall t b a. Foldable (StepWithDone t) => ((b, a) -> b, b, Step a t) -> b`
1155 ///
1156 /// ### Type Parameters
1157 ///
1158 /// * `FnBrand`: The brand of the cloneable function to use.
1159 /// * `B`: The type of the accumulator.
1160 /// * `A`: The type of the elements in the structure.
1161 /// * `F`: The type of the folding function.
1162 ///
1163 /// ### Parameters
1164 ///
1165 /// * `func`: The folding function.
1166 /// * `initial`: The initial value.
1167 /// * `fa`: The step to fold.
1168 ///
1169 /// ### Returns
1170 ///
1171 /// `func(initial, a)` if `fa` is `Loop(a)`, otherwise `initial`.
1172 ///
1173 /// ### Examples
1174 ///
1175 /// ```
1176 /// use fp_library::{brands::*, functions::*, types::*};
1177 ///
1178 /// assert_eq!(fold_left::<RcFnBrand, StepWithDoneBrand<()>, _, _, _>(|acc, x: i32| acc + x, 0, Step::Loop(5)), 5);
1179 /// assert_eq!(fold_left::<RcFnBrand, StepWithDoneBrand<i32>, _, _, _>(|acc, x: i32| acc + x, 0, Step::Done(1)), 0);
1180 /// ```
1181 fn fold_left<'a, FnBrand, B: 'a, A: 'a, F>(
1182 func: F,
1183 initial: B,
1184 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1185 ) -> B
1186 where
1187 F: Fn(B, A) -> B + 'a,
1188 FnBrand: CloneableFn + 'a,
1189 {
1190 match fa {
1191 Step::Loop(e) => func(initial, e),
1192 Step::Done(_) => initial,
1193 }
1194 }
1195
1196 /// Maps the value to a monoid and returns it (over loop).
1197 ///
1198 /// This method maps the element of the step to a monoid and then returns it (over loop).
1199 ///
1200 /// ### Type Signature
1201 ///
1202 /// `forall t m a. (Foldable (StepWithDone t), Monoid m) => ((a) -> m, Step a t) -> m`
1203 ///
1204 /// ### Type Parameters
1205 ///
1206 /// * `FnBrand`: The brand of the cloneable function to use.
1207 /// * `M`: The type of the monoid.
1208 /// * `A`: The type of the elements in the structure.
1209 /// * `F`: The type of the mapping function.
1210 ///
1211 /// ### Parameters
1212 ///
1213 /// * `func`: The mapping function.
1214 /// * `fa`: The step to fold.
1215 ///
1216 /// ### Returns
1217 ///
1218 /// `func(a)` if `fa` is `Loop(a)`, otherwise `M::empty()`.
1219 ///
1220 /// ### Examples
1221 ///
1222 /// ```
1223 /// use fp_library::{brands::*, functions::*, types::*};
1224 ///
1225 /// assert_eq!(
1226 /// fold_map::<RcFnBrand, StepWithDoneBrand<()>, _, _, _>(|x: i32| x.to_string(), Step::Loop(5)),
1227 /// "5".to_string()
1228 /// );
1229 /// assert_eq!(
1230 /// fold_map::<RcFnBrand, StepWithDoneBrand<i32>, _, _, _>(|x: i32| x.to_string(), Step::Done(1)),
1231 /// "".to_string()
1232 /// );
1233 /// ```
1234 fn fold_map<'a, FnBrand, M, A: 'a, F>(
1235 func: F,
1236 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1237 ) -> M
1238 where
1239 M: Monoid + 'a,
1240 F: Fn(A) -> M + 'a,
1241 FnBrand: CloneableFn + 'a,
1242 {
1243 match fa {
1244 Step::Loop(e) => func(e),
1245 Step::Done(_) => M::empty(),
1246 }
1247 }
1248}
1249
1250impl<DoneType: Clone + 'static> Traversable for StepWithDoneBrand<DoneType> {
1251 /// Traverses the step with an applicative function (over loop).
1252 ///
1253 /// This method maps the element of the step to a computation, evaluates it, and combines the result into an applicative context (over loop).
1254 ///
1255 /// ### Type Signature
1256 ///
1257 /// `forall t f b a. (Traversable (StepWithDone t), Applicative f) => (a -> f b, Step a t) -> f (Step b t)`
1258 ///
1259 /// ### Type Parameters
1260 ///
1261 /// * `F`: The applicative context.
1262 /// * `B`: The type of the elements in the resulting traversable structure.
1263 /// * `A`: The type of the elements in the traversable structure.
1264 /// * `Func`: The type of the function to apply.
1265 ///
1266 /// ### Parameters
1267 ///
1268 /// * `func`: The function to apply.
1269 /// * `ta`: The step to traverse.
1270 ///
1271 /// ### Returns
1272 ///
1273 /// The step wrapped in the applicative context.
1274 ///
1275 /// ### Examples
1276 ///
1277 /// ```
1278 /// use fp_library::{brands::*, functions::*, types::*};
1279 ///
1280 /// assert_eq!(
1281 /// traverse::<StepWithDoneBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Step::Loop(5)),
1282 /// Some(Step::Loop(10))
1283 /// );
1284 /// assert_eq!(
1285 /// traverse::<StepWithDoneBrand<i32>, OptionBrand, _, _, _>(|x: i32| Some(x * 2), Step::Done(1)),
1286 /// Some(Step::Done(1))
1287 /// );
1288 /// ```
1289 fn traverse<'a, F: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
1290 func: Func,
1291 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1292 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
1293 where
1294 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1295 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
1296 {
1297 match ta {
1298 Step::Loop(e) => F::map(|b| Step::Loop(b), func(e)),
1299 Step::Done(t) => F::pure(Step::Done(t)),
1300 }
1301 }
1302
1303 /// Sequences a step of applicative (over loop).
1304 ///
1305 /// This method evaluates the computation inside the step and accumulates the result into an applicative context (over loop).
1306 ///
1307 /// ### Type Signature
1308 ///
1309 /// `forall t f a. (Traversable (StepWithDone t), Applicative f) => (Step (f a) t) -> f (Step a t)`
1310 ///
1311 /// ### Type Parameters
1312 ///
1313 /// * `F`: The applicative context.
1314 /// * `A`: The type of the elements in the traversable structure.
1315 ///
1316 /// ### Parameters
1317 ///
1318 /// * `ta`: The step containing the applicative value.
1319 ///
1320 /// ### Returns
1321 ///
1322 /// The step wrapped in the applicative context.
1323 ///
1324 /// ### Examples
1325 ///
1326 /// ```
1327 /// use fp_library::{brands::*, functions::*, types::*};
1328 ///
1329 /// assert_eq!(
1330 /// sequence::<StepWithDoneBrand<()>, OptionBrand, _>(Step::Loop(Some(5))),
1331 /// Some(Step::Loop(5))
1332 /// );
1333 /// assert_eq!(
1334 /// sequence::<StepWithDoneBrand<i32>, OptionBrand, i32>(Step::Done::<Option<i32>, _>(1)),
1335 /// Some(Step::Done::<i32, i32>(1))
1336 /// );
1337 /// ```
1338 fn sequence<'a, F: Applicative, A: 'a + Clone>(
1339 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
1340 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
1341 where
1342 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1343 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1344 {
1345 match ta {
1346 Step::Loop(fe) => F::map(|e| Step::Loop(e), fe),
1347 Step::Done(t) => F::pure(Step::Done(t)),
1348 }
1349 }
1350}
1351
1352impl<DoneType: 'static, FnBrand: SendCloneableFn> ParFoldable<FnBrand>
1353 for StepWithDoneBrand<DoneType>
1354{
1355 /// Maps the value to a monoid and returns it, or returns empty, in parallel (over loop).
1356 ///
1357 /// This method maps the element of the step to a monoid and then returns it (over loop). The mapping operation may be executed in parallel.
1358 ///
1359 /// ### Type Signature
1360 ///
1361 /// `forall fn_brand t m a. (ParFoldable (StepWithDone t), Monoid m, Send m, Sync m) => (fn_brand a m, Step a t) -> m`
1362 ///
1363 /// ### Type Parameters
1364 ///
1365 /// * `FnBrand`: The brand of thread-safe function to use.
1366 /// * `M`: The monoid type (must be `Send + Sync`).
1367 /// * `A`: The element type (must be `Send + Sync`).
1368 ///
1369 /// ### Parameters
1370 ///
1371 /// * `func`: The thread-safe function to map each element to a monoid.
1372 /// * `fa`: The step to fold.
1373 ///
1374 /// ### Returns
1375 ///
1376 /// The combined monoid value.
1377 ///
1378 /// ### Examples
1379 ///
1380 /// ```
1381 /// use fp_library::{brands::*, classes::*, functions::*, types::*};
1382 ///
1383 /// let x: Step<i32, i32> = Step::Loop(5);
1384 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1385 /// assert_eq!(par_fold_map::<ArcFnBrand, StepWithDoneBrand<i32>, _, _>(f.clone(), x), "5".to_string());
1386 ///
1387 /// let x_done: Step<i32, i32> = Step::Done(1);
1388 /// assert_eq!(par_fold_map::<ArcFnBrand, StepWithDoneBrand<i32>, _, _>(f, x_done), "".to_string());
1389 /// ```
1390 fn par_fold_map<'a, M, A>(
1391 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
1392 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1393 ) -> M
1394 where
1395 A: 'a + Clone + Send + Sync,
1396 M: Monoid + Send + Sync + 'a,
1397 {
1398 match fa {
1399 Step::Loop(e) => func(e),
1400 Step::Done(_) => M::empty(),
1401 }
1402 }
1403
1404 /// Folds the step from the right in parallel (over loop).
1405 ///
1406 /// This method folds the step by applying a function from right to left, potentially in parallel (over loop).
1407 ///
1408 /// ### Type Signature
1409 ///
1410 /// `forall fn_brand t b a. ParFoldable (StepWithDone t) => (fn_brand (a, b) b, b, Step a t) -> b`
1411 ///
1412 /// ### Type Parameters
1413 ///
1414 /// * `FnBrand`: The brand of thread-safe function to use.
1415 /// * `B`: The accumulator type (must be `Send + Sync`).
1416 /// * `A`: The element type (must be `Send + Sync`).
1417 ///
1418 /// ### Parameters
1419 ///
1420 /// * `func`: The thread-safe function to apply to each element and the accumulator.
1421 /// * `initial`: The initial value.
1422 /// * `fa`: The step to fold.
1423 ///
1424 /// ### Returns
1425 ///
1426 /// The final accumulator value.
1427 ///
1428 /// ### Examples
1429 ///
1430 /// ```
1431 /// use fp_library::{brands::*, classes::*, functions::*, types::*};
1432 ///
1433 /// let x: Step<i32, i32> = Step::Loop(5);
1434 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1435 /// assert_eq!(par_fold_right::<ArcFnBrand, StepWithDoneBrand<i32>, _, _>(f.clone(), 10, x), 15);
1436 ///
1437 /// let x_done: Step<i32, i32> = Step::Done(1);
1438 /// assert_eq!(par_fold_right::<ArcFnBrand, StepWithDoneBrand<i32>, _, _>(f, 10, x_done), 10);
1439 /// ```
1440 fn par_fold_right<'a, B, A>(
1441 func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
1442 initial: B,
1443 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1444 ) -> B
1445 where
1446 A: 'a + Clone + Send + Sync,
1447 B: Send + Sync + 'a,
1448 {
1449 match fa {
1450 Step::Loop(e) => func((e, initial)),
1451 Step::Done(_) => initial,
1452 }
1453 }
1454}
1455
1456#[cfg(test)]
1457mod tests {
1458 use super::*;
1459 use crate::{
1460 brands::*,
1461 classes::{
1462 bifunctor::*, foldable::*, functor::*, lift::*, par_foldable::*, pointed::*,
1463 semiapplicative::*, semimonad::*, traversable::*,
1464 },
1465 functions::*,
1466 };
1467 use quickcheck::{Arbitrary, Gen};
1468 use quickcheck_macros::quickcheck;
1469
1470 impl<A: Arbitrary, B: Arbitrary> Arbitrary for Step<A, B> {
1471 fn arbitrary(g: &mut Gen) -> Self {
1472 if bool::arbitrary(g) {
1473 Step::Loop(A::arbitrary(g))
1474 } else {
1475 Step::Done(B::arbitrary(g))
1476 }
1477 }
1478 }
1479
1480 /// Tests the `is_loop` method.
1481 ///
1482 /// Verifies that `is_loop` returns true for `Loop` variants and false for `Done` variants.
1483 #[test]
1484 fn test_is_loop() {
1485 let step: Step<i32, i32> = Step::Loop(1);
1486 assert!(step.is_loop());
1487 assert!(!step.is_done());
1488 }
1489
1490 /// Tests the `is_done` method.
1491 ///
1492 /// Verifies that `is_done` returns true for `Done` variants and false for `Loop` variants.
1493 #[test]
1494 fn test_is_done() {
1495 let step: Step<i32, i32> = Step::Done(1);
1496 assert!(step.is_done());
1497 assert!(!step.is_loop());
1498 }
1499
1500 /// Tests the `map_loop` method.
1501 ///
1502 /// Verifies that `map_loop` transforms the value inside a `Loop` variant and leaves a `Done` variant unchanged.
1503 #[test]
1504 fn test_map_loop() {
1505 let step: Step<i32, i32> = Step::Loop(1);
1506 let mapped = step.map_loop(|x| x + 1);
1507 assert_eq!(mapped, Step::Loop(2));
1508
1509 let done: Step<i32, i32> = Step::Done(1);
1510 let mapped_done = done.map_loop(|x| x + 1);
1511 assert_eq!(mapped_done, Step::Done(1));
1512 }
1513
1514 /// Tests the `map_done` method.
1515 ///
1516 /// Verifies that `map_done` transforms the value inside a `Done` variant and leaves a `Loop` variant unchanged.
1517 #[test]
1518 fn test_map_done() {
1519 let step: Step<i32, i32> = Step::Done(1);
1520 let mapped = step.map_done(|x| x + 1);
1521 assert_eq!(mapped, Step::Done(2));
1522
1523 let loop_step: Step<i32, i32> = Step::Loop(1);
1524 let mapped_loop = loop_step.map_done(|x| x + 1);
1525 assert_eq!(mapped_loop, Step::Loop(1));
1526 }
1527
1528 /// Tests the `bimap` method.
1529 ///
1530 /// Verifies that `bimap` transforms the value inside both `Loop` and `Done` variants using the appropriate function.
1531 #[test]
1532 fn test_bimap() {
1533 let step: Step<i32, i32> = Step::Loop(1);
1534 let mapped = step.bimap(|x| x + 1, |x| x * 2);
1535 assert_eq!(mapped, Step::Loop(2));
1536
1537 let done: Step<i32, i32> = Step::Done(1);
1538 let mapped_done = done.bimap(|x| x + 1, |x| x * 2);
1539 assert_eq!(mapped_done, Step::Done(2));
1540 }
1541
1542 /// Tests `Functor` implementation for `StepWithLoopBrand`.
1543 #[test]
1544 fn test_functor_step_with_loop() {
1545 let step: Step<i32, i32> = Step::Done(5);
1546 assert_eq!(map::<StepWithLoopBrand<_>, _, _, _>(|x: i32| x * 2, step), Step::Done(10));
1547
1548 let loop_step: Step<i32, i32> = Step::Loop(5);
1549 assert_eq!(map::<StepWithLoopBrand<_>, _, _, _>(|x: i32| x * 2, loop_step), Step::Loop(5));
1550 }
1551
1552 /// Tests `Functor` implementation for `StepWithDoneBrand`.
1553 #[test]
1554 fn test_functor_step_with_done() {
1555 let step: Step<i32, i32> = Step::Loop(5);
1556 assert_eq!(map::<StepWithDoneBrand<_>, _, _, _>(|x: i32| x * 2, step), Step::Loop(10));
1557
1558 let done_step: Step<i32, i32> = Step::Done(5);
1559 assert_eq!(map::<StepWithDoneBrand<_>, _, _, _>(|x: i32| x * 2, done_step), Step::Done(5));
1560 }
1561
1562 /// Tests `Bifunctor` implementation for `StepBrand`.
1563 #[test]
1564 fn test_bifunctor_step() {
1565 let step: Step<i32, i32> = Step::Loop(5);
1566 assert_eq!(bimap::<StepBrand, _, _, _, _, _, _>(|a| a + 1, |b| b * 2, step), Step::Loop(6));
1567
1568 let done: Step<i32, i32> = Step::Done(5);
1569 assert_eq!(
1570 bimap::<StepBrand, _, _, _, _, _, _>(|a| a + 1, |b| b * 2, done),
1571 Step::Done(10)
1572 );
1573 }
1574
1575 // Functor Laws for StepWithLoopBrand
1576
1577 #[quickcheck]
1578 fn functor_identity_step_with_loop(x: Step<i32, i32>) -> bool {
1579 map::<StepWithLoopBrand<i32>, _, _, _>(identity, x) == x
1580 }
1581
1582 #[quickcheck]
1583 fn functor_composition_step_with_loop(x: Step<i32, i32>) -> bool {
1584 let f = |x: i32| x.wrapping_add(1);
1585 let g = |x: i32| x.wrapping_mul(2);
1586 map::<StepWithLoopBrand<i32>, _, _, _>(compose(f, g), x)
1587 == map::<StepWithLoopBrand<i32>, _, _, _>(
1588 f,
1589 map::<StepWithLoopBrand<i32>, _, _, _>(g, x),
1590 )
1591 }
1592
1593 // Functor Laws for StepWithDoneBrand
1594
1595 #[quickcheck]
1596 fn functor_identity_step_with_done(x: Step<i32, i32>) -> bool {
1597 map::<StepWithDoneBrand<i32>, _, _, _>(identity, x) == x
1598 }
1599
1600 #[quickcheck]
1601 fn functor_composition_step_with_done(x: Step<i32, i32>) -> bool {
1602 let f = |x: i32| x.wrapping_add(1);
1603 let g = |x: i32| x.wrapping_mul(2);
1604 map::<StepWithDoneBrand<i32>, _, _, _>(compose(f, g), x)
1605 == map::<StepWithDoneBrand<i32>, _, _, _>(
1606 f,
1607 map::<StepWithDoneBrand<i32>, _, _, _>(g, x),
1608 )
1609 }
1610
1611 // Bifunctor Laws for StepBrand
1612
1613 #[quickcheck]
1614 fn bifunctor_identity_step(x: Step<i32, i32>) -> bool {
1615 bimap::<StepBrand, _, _, _, _, _, _>(identity, identity, x) == x
1616 }
1617
1618 #[quickcheck]
1619 fn bifunctor_composition_step(x: Step<i32, i32>) -> bool {
1620 let f = |x: i32| x.wrapping_add(1);
1621 let g = |x: i32| x.wrapping_mul(2);
1622 let h = |x: i32| x.wrapping_sub(1);
1623 let i = |x: i32| if x == 0 { 0 } else { x.wrapping_div(2) };
1624
1625 bimap::<StepBrand, _, _, _, _, _, _>(compose(f, g), compose(h, i), x)
1626 == bimap::<StepBrand, _, _, _, _, _, _>(
1627 f,
1628 h,
1629 bimap::<StepBrand, _, _, _, _, _, _>(g, i, x),
1630 )
1631 }
1632
1633 // Lift Tests
1634
1635 /// Tests the `lift2` function for `StepWithLoopBrand`.
1636 ///
1637 /// Verifies that `lift2` correctly combines two `Step` values using a binary function,
1638 /// handling `Done` and `Loop` variants according to the `Lift` implementation.
1639 #[test]
1640 fn test_lift2_step_with_loop() {
1641 let s1: Step<i32, i32> = Step::Done(1);
1642 let s2: Step<i32, i32> = Step::Done(2);
1643 let s3: Step<i32, i32> = Step::Loop(3);
1644
1645 assert_eq!(
1646 lift2::<StepWithLoopBrand<i32>, _, _, _, _>(|x, y| x + y, s1, s2),
1647 Step::Done(3)
1648 );
1649 assert_eq!(
1650 lift2::<StepWithLoopBrand<i32>, _, _, _, _>(|x, y| x + y, s1, s3),
1651 Step::Loop(3)
1652 );
1653 }
1654
1655 /// Tests the `lift2` function for `StepWithDoneBrand`.
1656 ///
1657 /// Verifies that `lift2` correctly combines two `Step` values using a binary function,
1658 /// handling `Done` and `Loop` variants according to the `Lift` implementation.
1659 #[test]
1660 fn test_lift2_step_with_done() {
1661 let s1: Step<i32, i32> = Step::Loop(1);
1662 let s2: Step<i32, i32> = Step::Loop(2);
1663 let s3: Step<i32, i32> = Step::Done(3);
1664
1665 assert_eq!(
1666 lift2::<StepWithDoneBrand<i32>, _, _, _, _>(|x, y| x + y, s1, s2),
1667 Step::Loop(3)
1668 );
1669 assert_eq!(
1670 lift2::<StepWithDoneBrand<i32>, _, _, _, _>(|x, y| x + y, s1, s3),
1671 Step::Done(3)
1672 );
1673 }
1674
1675 // Pointed Tests
1676
1677 /// Tests the `pure` function for `StepWithLoopBrand`.
1678 ///
1679 /// Verifies that `pure` wraps a value into a `Step::Done` variant.
1680 #[test]
1681 fn test_pointed_step_with_loop() {
1682 assert_eq!(pure::<StepWithLoopBrand<()>, _>(5), Step::Done(5));
1683 }
1684
1685 /// Tests the `pure` function for `StepWithDoneBrand`.
1686 ///
1687 /// Verifies that `pure` wraps a value into a `Step::Loop` variant.
1688 #[test]
1689 fn test_pointed_step_with_done() {
1690 assert_eq!(pure::<StepWithDoneBrand<()>, _>(5), Step::Loop(5));
1691 }
1692
1693 // Semiapplicative Tests
1694
1695 /// Tests the `apply` function for `StepWithLoopBrand`.
1696 ///
1697 /// Verifies that `apply` correctly applies a wrapped function to a wrapped value,
1698 /// handling `Done` and `Loop` variants.
1699 #[test]
1700 fn test_apply_step_with_loop() {
1701 let f =
1702 pure::<StepWithLoopBrand<()>, _>(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
1703 let x = pure::<StepWithLoopBrand<()>, _>(5);
1704 assert_eq!(apply::<RcFnBrand, StepWithLoopBrand<()>, _, _>(f, x), Step::Done(10));
1705
1706 let loop_step: Step<i32, _> = Step::Loop(1);
1707 let f_loop =
1708 pure::<StepWithLoopBrand<i32>, _>(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
1709 assert_eq!(
1710 apply::<RcFnBrand, StepWithLoopBrand<i32>, _, _>(f_loop, loop_step),
1711 Step::Loop(1)
1712 );
1713 }
1714
1715 /// Tests the `apply` function for `StepWithDoneBrand`.
1716 ///
1717 /// Verifies that `apply` correctly applies a wrapped function to a wrapped value,
1718 /// handling `Done` and `Loop` variants.
1719 #[test]
1720 fn test_apply_step_with_done() {
1721 let f =
1722 pure::<StepWithDoneBrand<()>, _>(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
1723 let x = pure::<StepWithDoneBrand<()>, _>(5);
1724 assert_eq!(apply::<RcFnBrand, StepWithDoneBrand<()>, _, _>(f, x), Step::Loop(10));
1725
1726 let done_step: Step<_, i32> = Step::Done(1);
1727 let f_done =
1728 pure::<StepWithDoneBrand<i32>, _>(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
1729 assert_eq!(
1730 apply::<RcFnBrand, StepWithDoneBrand<i32>, _, _>(f_done, done_step),
1731 Step::Done(1)
1732 );
1733 }
1734
1735 // Semimonad Tests
1736
1737 /// Tests the `bind` function for `StepWithLoopBrand`.
1738 ///
1739 /// Verifies that `bind` correctly chains computations, handling `Done` and `Loop` variants.
1740 #[test]
1741 fn test_bind_step_with_loop() {
1742 let x = pure::<StepWithLoopBrand<()>, _>(5);
1743 assert_eq!(
1744 bind::<StepWithLoopBrand<()>, _, _, _>(x, |i| pure::<StepWithLoopBrand<()>, _>(i * 2)),
1745 Step::Done(10)
1746 );
1747
1748 let loop_step: Step<i32, i32> = Step::Loop(1);
1749 assert_eq!(
1750 bind::<StepWithLoopBrand<i32>, _, _, _>(
1751 loop_step,
1752 |i| pure::<StepWithLoopBrand<i32>, _>(i * 2)
1753 ),
1754 Step::Loop(1)
1755 );
1756 }
1757
1758 /// Tests the `bind` function for `StepWithDoneBrand`.
1759 ///
1760 /// Verifies that `bind` correctly chains computations, handling `Done` and `Loop` variants.
1761 #[test]
1762 fn test_bind_step_with_done() {
1763 let x = pure::<StepWithDoneBrand<()>, _>(5);
1764 assert_eq!(
1765 bind::<StepWithDoneBrand<()>, _, _, _>(x, |i| pure::<StepWithDoneBrand<()>, _>(i * 2)),
1766 Step::Loop(10)
1767 );
1768
1769 let done_step: Step<i32, i32> = Step::Done(1);
1770 assert_eq!(
1771 bind::<StepWithDoneBrand<i32>, _, _, _>(
1772 done_step,
1773 |i| pure::<StepWithDoneBrand<i32>, _>(i * 2)
1774 ),
1775 Step::Done(1)
1776 );
1777 }
1778
1779 // Foldable Tests
1780
1781 /// Tests `Foldable` methods for `StepWithLoopBrand`.
1782 ///
1783 /// Verifies `fold_right`, `fold_left`, and `fold_map` behavior for `Done` and `Loop` variants.
1784 #[test]
1785 fn test_foldable_step_with_loop() {
1786 let x = pure::<StepWithLoopBrand<()>, _>(5);
1787 assert_eq!(
1788 fold_right::<RcFnBrand, StepWithLoopBrand<()>, _, _, _>(|a, b| a + b, 10, x),
1789 15
1790 );
1791 assert_eq!(fold_left::<RcFnBrand, StepWithLoopBrand<()>, _, _, _>(|b, a| b + a, 10, x), 15);
1792 assert_eq!(
1793 fold_map::<RcFnBrand, StepWithLoopBrand<()>, _, _, _>(|a: i32| a.to_string(), x),
1794 "5"
1795 );
1796
1797 let loop_step: Step<i32, i32> = Step::Loop(1);
1798 assert_eq!(
1799 fold_right::<RcFnBrand, StepWithLoopBrand<i32>, _, _, _>(|a, b| a + b, 10, loop_step),
1800 10
1801 );
1802 }
1803
1804 /// Tests `Foldable` methods for `StepWithDoneBrand`.
1805 ///
1806 /// Verifies `fold_right`, `fold_left`, and `fold_map` behavior for `Done` and `Loop` variants.
1807 #[test]
1808 fn test_foldable_step_with_done() {
1809 let x = pure::<StepWithDoneBrand<()>, _>(5);
1810 assert_eq!(
1811 fold_right::<RcFnBrand, StepWithDoneBrand<()>, _, _, _>(|a, b| a + b, 10, x),
1812 15
1813 );
1814 assert_eq!(fold_left::<RcFnBrand, StepWithDoneBrand<()>, _, _, _>(|b, a| b + a, 10, x), 15);
1815 assert_eq!(
1816 fold_map::<RcFnBrand, StepWithDoneBrand<()>, _, _, _>(|a: i32| a.to_string(), x),
1817 "5"
1818 );
1819
1820 let done_step: Step<i32, i32> = Step::Done(1);
1821 assert_eq!(
1822 fold_right::<RcFnBrand, StepWithDoneBrand<i32>, _, _, _>(|a, b| a + b, 10, done_step),
1823 10
1824 );
1825 }
1826
1827 // Traversable Tests
1828
1829 /// Tests the `traverse` function for `StepWithLoopBrand`.
1830 ///
1831 /// Verifies that `traverse` correctly maps and sequences effects over `Step`.
1832 #[test]
1833 fn test_traversable_step_with_loop() {
1834 let x = pure::<StepWithLoopBrand<()>, _>(5);
1835 assert_eq!(
1836 traverse::<StepWithLoopBrand<()>, OptionBrand, _, _, _>(|a| Some(a * 2), x),
1837 Some(Step::Done(10))
1838 );
1839
1840 let loop_step: Step<i32, i32> = Step::Loop(1);
1841 assert_eq!(
1842 traverse::<StepWithLoopBrand<i32>, OptionBrand, _, _, _>(|a| Some(a * 2), loop_step),
1843 Some(Step::Loop(1))
1844 );
1845 }
1846
1847 /// Tests the `traverse` function for `StepWithDoneBrand`.
1848 ///
1849 /// Verifies that `traverse` correctly maps and sequences effects over `Step`.
1850 #[test]
1851 fn test_traversable_step_with_done() {
1852 let x = pure::<StepWithDoneBrand<()>, _>(5);
1853 assert_eq!(
1854 traverse::<StepWithDoneBrand<()>, OptionBrand, _, _, _>(|a| Some(a * 2), x),
1855 Some(Step::Loop(10))
1856 );
1857
1858 let done_step: Step<i32, i32> = Step::Done(1);
1859 assert_eq!(
1860 traverse::<StepWithDoneBrand<i32>, OptionBrand, _, _, _>(|a| Some(a * 2), done_step),
1861 Some(Step::Done(1))
1862 );
1863 }
1864
1865 // ParFoldable Tests
1866
1867 /// Tests `par_fold_map` for `StepWithLoopBrand`.
1868 ///
1869 /// Verifies parallel folding behavior (conceptually, as it delegates to sequential for simple types).
1870 #[test]
1871 fn test_par_foldable_step_with_loop() {
1872 let x = pure::<StepWithLoopBrand<()>, _>(5);
1873 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|a: i32| a.to_string());
1874 assert_eq!(par_fold_map::<ArcFnBrand, StepWithLoopBrand<()>, _, _>(f, x), "5");
1875 }
1876
1877 /// Tests `par_fold_map` for `StepWithDoneBrand`.
1878 ///
1879 /// Verifies parallel folding behavior.
1880 #[test]
1881 fn test_par_foldable_step_with_done() {
1882 let x = pure::<StepWithDoneBrand<()>, _>(5);
1883 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|a: i32| a.to_string());
1884 assert_eq!(par_fold_map::<ArcFnBrand, StepWithDoneBrand<()>, _, _>(f, x), "5");
1885 }
1886
1887 // Monad Laws for StepWithLoopBrand
1888
1889 /// Verifies the Left Identity law for `StepWithLoopBrand` Monad.
1890 #[quickcheck]
1891 fn monad_left_identity_step_with_loop(a: i32) -> bool {
1892 let f = |x: i32| pure::<StepWithLoopBrand<i32>, _>(x.wrapping_mul(2));
1893 bind::<StepWithLoopBrand<i32>, _, _, _>(pure::<StepWithLoopBrand<i32>, _>(a), f) == f(a)
1894 }
1895
1896 /// Verifies the Right Identity law for `StepWithLoopBrand` Monad.
1897 #[quickcheck]
1898 fn monad_right_identity_step_with_loop(x: Step<i32, i32>) -> bool {
1899 bind::<StepWithLoopBrand<i32>, _, _, _>(x, pure::<StepWithLoopBrand<i32>, _>) == x
1900 }
1901
1902 /// Verifies the Associativity law for `StepWithLoopBrand` Monad.
1903 #[quickcheck]
1904 fn monad_associativity_step_with_loop(x: Step<i32, i32>) -> bool {
1905 let f = |x: i32| pure::<StepWithLoopBrand<i32>, _>(x.wrapping_mul(2));
1906 let g = |x: i32| pure::<StepWithLoopBrand<i32>, _>(x.wrapping_add(1));
1907 bind::<StepWithLoopBrand<i32>, _, _, _>(bind::<StepWithLoopBrand<i32>, _, _, _>(x, f), g)
1908 == bind::<StepWithLoopBrand<i32>, _, _, _>(x, |a| {
1909 bind::<StepWithLoopBrand<i32>, _, _, _>(f(a), g)
1910 })
1911 }
1912
1913 // Monad Laws for StepWithDoneBrand
1914
1915 /// Verifies the Left Identity law for `StepWithDoneBrand` Monad.
1916 #[quickcheck]
1917 fn monad_left_identity_step_with_done(a: i32) -> bool {
1918 let f = |x: i32| pure::<StepWithDoneBrand<i32>, _>(x.wrapping_mul(2));
1919 bind::<StepWithDoneBrand<i32>, _, _, _>(pure::<StepWithDoneBrand<i32>, _>(a), f) == f(a)
1920 }
1921
1922 /// Verifies the Right Identity law for `StepWithDoneBrand` Monad.
1923 #[quickcheck]
1924 fn monad_right_identity_step_with_done(x: Step<i32, i32>) -> bool {
1925 bind::<StepWithDoneBrand<i32>, _, _, _>(x, pure::<StepWithDoneBrand<i32>, _>) == x
1926 }
1927
1928 /// Verifies the Associativity law for `StepWithDoneBrand` Monad.
1929 #[quickcheck]
1930 fn monad_associativity_step_with_done(x: Step<i32, i32>) -> bool {
1931 let f = |x: i32| pure::<StepWithDoneBrand<i32>, _>(x.wrapping_mul(2));
1932 let g = |x: i32| pure::<StepWithDoneBrand<i32>, _>(x.wrapping_add(1));
1933 bind::<StepWithDoneBrand<i32>, _, _, _>(bind::<StepWithDoneBrand<i32>, _, _, _>(x, f), g)
1934 == bind::<StepWithDoneBrand<i32>, _, _, _>(x, |a| {
1935 bind::<StepWithDoneBrand<i32>, _, _, _>(f(a), g)
1936 })
1937 }
1938}