1#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::{
9 Apply,
10 brands::{
11 PairBrand,
12 PairFirstAppliedBrand,
13 PairSecondAppliedBrand,
14 },
15 classes::{
16 Applicative,
17 ApplyFirst,
18 ApplySecond,
19 Bifoldable,
20 Bifunctor,
21 Bitraversable,
22 CloneableFn,
23 Foldable,
24 Functor,
25 Lift,
26 MonadRec,
27 Monoid,
28 Pointed,
29 Semiapplicative,
30 Semigroup,
31 Semimonad,
32 Traversable,
33 },
34 impl_kind,
35 kinds::*,
36 },
37 core::ops::ControlFlow,
38 fp_macros::*,
39 };
40
41 #[document_type_parameters("The type of the first value.", "The type of the second value.")]
56 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
59 pub struct Pair<First, Second>(
60 pub First,
62 pub Second,
64 );
65
66 impl_kind! {
67 for PairBrand {
68 type Of<First,Second> = Pair<First, Second>;
69 }
70 }
71
72 impl_kind! {
73 for PairBrand {
74 type Of<'a, First: 'a, Second: 'a>: 'a = Pair<First, Second>;
75 }
76 }
77
78 #[document_type_parameters("The type of the first value.", "The type of the second value.")]
79 #[document_parameters("The pair instance.")]
80 impl<First, Second> Pair<First, Second> {
81 #[document_signature]
85 #[document_type_parameters(
87 "The type of the mapped first value.",
88 "The type of the mapped second value."
89 )]
90 #[document_parameters(
92 "The function to apply to the first value.",
93 "The function to apply to the second value."
94 )]
95 #[document_returns("A new pair containing the mapped values.")]
97 #[document_examples]
99 pub fn bimap<B, D>(
107 self,
108 f: impl FnOnce(First) -> B,
109 g: impl FnOnce(Second) -> D,
110 ) -> Pair<B, D> {
111 Pair(f(self.0), g(self.1))
112 }
113
114 #[document_signature]
118 #[document_type_parameters("The type of the mapped first value.")]
120 #[document_parameters("The function to apply to the first value.")]
122 #[document_returns("A new pair with the transformed first value.")]
124 #[document_examples]
126 pub fn map_first<B>(
134 self,
135 f: impl FnOnce(First) -> B,
136 ) -> Pair<B, Second> {
137 Pair(f(self.0), self.1)
138 }
139
140 #[document_signature]
144 #[document_type_parameters("The type of the mapped second value.")]
146 #[document_parameters("The function to apply to the second value.")]
148 #[document_returns("A new pair with the transformed second value.")]
150 #[document_examples]
152 pub fn map_second<D>(
160 self,
161 g: impl FnOnce(Second) -> D,
162 ) -> Pair<First, D> {
163 Pair(self.0, g(self.1))
164 }
165
166 #[document_signature]
171 #[document_type_parameters("The result type.")]
173 #[document_parameters(
175 "The function to apply to the first value.",
176 "The function to apply to the second value.",
177 "The function to combine the results."
178 )]
179 #[document_returns("The combined result.")]
181 #[document_examples]
183 pub fn fold<C>(
192 self,
193 f: impl FnOnce(First) -> C,
194 g: impl FnOnce(Second) -> C,
195 combine: impl FnOnce(C, C) -> C,
196 ) -> C {
197 combine(f(self.0), g(self.1))
198 }
199
200 #[document_signature]
204 #[document_type_parameters("The accumulator type.")]
206 #[document_parameters(
208 "The step function for the first value.",
209 "The step function for the second value.",
210 "The initial accumulator."
211 )]
212 #[document_returns("The result of folding: `f(first, g(second, z))`.")]
214 #[document_examples]
216 pub fn bi_fold_right<C>(
224 self,
225 f: impl FnOnce(First, C) -> C,
226 g: impl FnOnce(Second, C) -> C,
227 z: C,
228 ) -> C {
229 f(self.0, g(self.1, z))
230 }
231
232 #[document_signature]
236 #[document_type_parameters("The accumulator type.")]
238 #[document_parameters(
240 "The step function for the first value.",
241 "The step function for the second value.",
242 "The initial accumulator."
243 )]
244 #[document_returns("The result of folding: `g(f(z, first), second)`.")]
246 #[document_examples]
248 pub fn bi_fold_left<C>(
256 self,
257 f: impl FnOnce(C, First) -> C,
258 g: impl FnOnce(C, Second) -> C,
259 z: C,
260 ) -> C {
261 g(f(z, self.0), self.1)
262 }
263
264 #[document_signature]
268 #[document_type_parameters("The monoid type.")]
270 #[document_parameters(
272 "The function mapping the first value to the monoid.",
273 "The function mapping the second value to the monoid."
274 )]
275 #[document_returns("The combined monoid value.")]
277 #[document_examples]
279 pub fn bi_fold_map<M: Semigroup>(
287 self,
288 f: impl FnOnce(First) -> M,
289 g: impl FnOnce(Second) -> M,
290 ) -> M {
291 Semigroup::append(f(self.0), g(self.1))
292 }
293 }
294
295 #[document_type_parameters(
296 "The lifetime of the values.",
297 "The type of the first value.",
298 "The type of the second value."
299 )]
300 #[document_parameters("The pair instance.")]
301 impl<'a, First: 'a, Second: 'a> Pair<First, Second> {
302 #[document_signature]
306 #[document_type_parameters(
308 "The output type for the first value.",
309 "The output type for the second value.",
310 "The applicative context."
311 )]
312 #[document_parameters(
314 "The function for the first value.",
315 "The function for the second value."
316 )]
317 #[document_returns("A pair of the transformed values wrapped in the applicative context.")]
319 #[document_examples]
321 pub fn bi_traverse<C: 'a + Clone, D: 'a + Clone, F: Applicative>(
333 self,
334 f: impl Fn(First) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
335 g: impl Fn(Second) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
336 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Pair<C, D>>)
337 where
338 Pair<C, D>: Clone, {
339 F::lift2(|c, d| Pair(c, d), f(self.0), g(self.1))
340 }
341 }
342
343 #[document_type_parameters("The type of the first value.", "The type of the second value.")]
344 #[document_parameters("The pair instance.")]
345 impl<First: Semigroup, Second> Pair<First, Second> {
346 #[document_signature]
351 #[document_type_parameters("The type of the new second value.")]
353 #[document_parameters("The function to apply to the second value.")]
355 #[document_returns(
357 "A new pair where the first values are combined and the second value is transformed."
358 )]
359 #[document_examples]
361 pub fn bind<C>(
371 self,
372 f: impl FnOnce(Second) -> Pair<First, C>,
373 ) -> Pair<First, C> {
374 let Pair(first, second) = self;
375 let Pair(next_first, next_second) = f(second);
376 Pair(Semigroup::append(first, next_first), next_second)
377 }
378 }
379
380 #[document_type_parameters("The type of the first value.", "The type of the second value.")]
381 #[document_parameters("The pair instance.")]
382 impl<First, Second: Semigroup> Pair<First, Second> {
383 #[document_signature]
388 #[document_type_parameters("The type of the new first value.")]
390 #[document_parameters("The function to apply to the first value.")]
392 #[document_returns(
394 "A new pair where the first value is transformed and the second values are combined."
395 )]
396 #[document_examples]
398 pub fn bind_first<C>(
408 self,
409 f: impl FnOnce(First) -> Pair<C, Second>,
410 ) -> Pair<C, Second> {
411 let Pair(first, second) = self;
412 let Pair(next_first, next_second) = f(first);
413 Pair(next_first, Semigroup::append(second, next_second))
414 }
415 }
416
417 impl Bifunctor for PairBrand {
418 #[document_signature]
422 #[document_type_parameters(
424 "The lifetime of the values.",
425 "The type of the first value.",
426 "The type of the mapped first value.",
427 "The type of the second value.",
428 "The type of the mapped second value."
429 )]
430 #[document_parameters(
432 "The function to apply to the first value.",
433 "The function to apply to the second value.",
434 "The pair to map over."
435 )]
436 #[document_returns("A new pair containing the mapped values.")]
438 #[document_examples]
439 fn bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
452 f: impl Fn(A) -> B + 'a,
453 g: impl Fn(C) -> D + 'a,
454 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
455 ) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>) {
456 p.bimap(f, g)
457 }
458 }
459
460 impl Bifoldable for PairBrand {
461 #[document_signature]
465 #[document_type_parameters(
467 "The lifetime of the values.",
468 "The brand of the cloneable function to use.",
469 "The type of the first value.",
470 "The type of the second value.",
471 "The accumulator type."
472 )]
473 #[document_parameters(
475 "The step function for the first value.",
476 "The step function for the second value.",
477 "The initial accumulator.",
478 "The pair to fold."
479 )]
480 #[document_returns("`f(a, g(b, z))`.")]
482 #[document_examples]
483 fn bi_fold_right<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
498 f: impl Fn(A, C) -> C + 'a,
499 g: impl Fn(B, C) -> C + 'a,
500 z: C,
501 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
502 ) -> C {
503 p.bi_fold_right(f, g, z)
504 }
505
506 #[document_signature]
510 #[document_type_parameters(
512 "The lifetime of the values.",
513 "The brand of the cloneable function to use.",
514 "The type of the first value.",
515 "The type of the second value.",
516 "The accumulator type."
517 )]
518 #[document_parameters(
520 "The step function for the first value.",
521 "The step function for the second value.",
522 "The initial accumulator.",
523 "The pair to fold."
524 )]
525 #[document_returns("`g(f(z, a), b)`.")]
527 #[document_examples]
528 fn bi_fold_left<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
543 f: impl Fn(C, A) -> C + 'a,
544 g: impl Fn(C, B) -> C + 'a,
545 z: C,
546 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
547 ) -> C {
548 p.bi_fold_left(f, g, z)
549 }
550
551 #[document_signature]
555 #[document_type_parameters(
557 "The lifetime of the values.",
558 "The brand of the cloneable function to use.",
559 "The type of the first value.",
560 "The type of the second value.",
561 "The monoid type."
562 )]
563 #[document_parameters(
565 "The function mapping the first value to the monoid.",
566 "The function mapping the second value to the monoid.",
567 "The pair to fold."
568 )]
569 #[document_returns("`Semigroup::append(f(a), g(b))`.")]
571 #[document_examples]
572 fn bi_fold_map<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, M>(
590 f: impl Fn(A) -> M + 'a,
591 g: impl Fn(B) -> M + 'a,
592 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
593 ) -> M
594 where
595 M: Monoid + 'a, {
596 p.bi_fold_map(f, g)
597 }
598 }
599
600 impl Bitraversable for PairBrand {
601 #[document_signature]
606 #[document_type_parameters(
608 "The lifetime of the values.",
609 "The type of the first value.",
610 "The type of the second value.",
611 "The output type for the first value.",
612 "The output type for the second value.",
613 "The applicative context."
614 )]
615 #[document_parameters(
617 "The function applied to the first value.",
618 "The function applied to the second value.",
619 "The pair to traverse."
620 )]
621 #[document_returns("`lift2(Pair, f(a), g(b))`.")]
623 #[document_examples]
624 fn bi_traverse<
643 'a,
644 A: 'a + Clone,
645 B: 'a + Clone,
646 C: 'a + Clone,
647 D: 'a + Clone,
648 F: Applicative,
649 >(
650 f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
651 g: impl Fn(B) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
652 p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
653 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, C, D>)>)
654 {
655 p.bi_traverse::<C, D, F>(f, g)
656 }
657 }
658
659 impl_kind! {
662 #[document_type_parameters("The type of the first value in the pair.")]
663 impl<First: 'static> for PairFirstAppliedBrand<First> {
664 type Of<'a, A: 'a>: 'a = Pair<First, A>;
665 }
666 }
667
668 #[document_type_parameters("The type of the first value in the pair.")]
669 impl<First: 'static> Functor for PairFirstAppliedBrand<First> {
670 #[document_signature]
674 #[document_type_parameters(
676 "The lifetime of the values.",
677 "The type of the second value.",
678 "The type of the result of applying the function."
679 )]
680 #[document_parameters(
682 "The function to apply to the second value.",
683 "The pair to map over."
684 )]
685 #[document_returns(
687 "A new pair containing the result of applying the function to the second value."
688 )]
689 #[document_examples]
690 fn map<'a, A: 'a, B: 'a>(
701 func: impl Fn(A) -> B + 'a,
702 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
703 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
704 fa.map_second(func)
705 }
706 }
707
708 #[document_type_parameters("The type of the first value in the pair.")]
709 impl<First: Clone + 'static> Lift for PairFirstAppliedBrand<First>
710 where
711 First: Semigroup,
712 {
713 #[document_signature]
717 #[document_type_parameters(
719 "The lifetime of the values.",
720 "The type of the first second value.",
721 "The type of the second second value.",
722 "The type of the result second value."
723 )]
724 #[document_parameters(
726 "The binary function to apply to the second values.",
727 "The first pair.",
728 "The second pair."
729 )]
730 #[document_returns(
732 "A new pair where the first values are combined using `Semigroup::append` and the second values are combined using `f`."
733 )]
734 #[document_examples]
735 fn lift2<'a, A, B, C>(
753 func: impl Fn(A, B) -> C + 'a,
754 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
755 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
756 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
757 where
758 A: Clone + 'a,
759 B: Clone + 'a,
760 C: 'a, {
761 let Pair(fa_first, fa_second) = fa;
762 let Pair(fb_first, fb_second) = fb;
763 Pair(Semigroup::append(fa_first, fb_first), func(fa_second, fb_second))
764 }
765 }
766
767 #[document_type_parameters("The type of the first value in the pair.")]
768 impl<First: Clone + 'static> Pointed for PairFirstAppliedBrand<First>
769 where
770 First: Monoid,
771 {
772 #[document_signature]
776 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
778 #[document_parameters("The value to wrap.")]
780 #[document_returns("A pair containing the empty value of the first type and `a`.")]
782 #[document_examples]
784 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
795 Pair(Monoid::empty(), a)
796 }
797 }
798
799 #[document_type_parameters("The type of the first value in the pair.")]
800 impl<First: Clone + Semigroup + 'static> ApplyFirst for PairFirstAppliedBrand<First> {}
801
802 #[document_type_parameters("The type of the first value in the pair.")]
803 impl<First: Clone + Semigroup + 'static> ApplySecond for PairFirstAppliedBrand<First> {}
804
805 #[document_type_parameters("The type of the first value in the pair.")]
806 impl<First: Clone + 'static> Semiapplicative for PairFirstAppliedBrand<First>
807 where
808 First: Semigroup,
809 {
810 #[document_signature]
814 #[document_type_parameters(
816 "The lifetime of the values.",
817 "The brand of the cloneable function wrapper.",
818 "The type of the input value.",
819 "The type of the output value."
820 )]
821 #[document_parameters(
823 "The pair containing the function.",
824 "The pair containing the value."
825 )]
826 #[document_returns(
828 "A new pair where the first values are combined and the function is applied to the second value."
829 )]
830 #[document_examples]
831 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
846 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
847 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
848 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
849 Pair(Semigroup::append(ff.0, fa.0), ff.1(fa.1))
850 }
851 }
852
853 #[document_type_parameters("The type of the first value in the pair.")]
854 impl<First: Clone + 'static> Semimonad for PairFirstAppliedBrand<First>
855 where
856 First: Semigroup,
857 {
858 #[document_signature]
862 #[document_type_parameters(
864 "The lifetime of the values.",
865 "The type of the result of the first computation.",
866 "The type of the result of the second computation."
867 )]
868 #[document_parameters("The first pair.", "The function to apply to the second value.")]
870 #[document_returns("A new pair where the first values are combined.")]
872 #[document_examples]
874 fn bind<'a, A: 'a, B: 'a>(
891 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
892 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
893 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
894 ma.bind(func)
895 }
896 }
897
898 #[document_type_parameters("The type of the first value in the pair.")]
900 impl<First: Clone + 'static> MonadRec for PairFirstAppliedBrand<First>
901 where
902 First: Monoid,
903 {
904 #[document_signature]
912 #[document_type_parameters(
914 "The lifetime of the computation.",
915 "The type of the initial value and loop state.",
916 "The type of the result."
917 )]
918 #[document_parameters("The step function.", "The initial value.")]
920 #[document_returns("A pair with the accumulated first value and the final result.")]
922 #[document_examples]
924 fn tail_rec_m<'a, A: 'a, B: 'a>(
948 func: impl Fn(
949 A,
950 )
951 -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
952 + 'a,
953 initial: A,
954 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
955 let mut acc: First = Monoid::empty();
956 let mut current = initial;
957 loop {
958 let Pair(first, step) = func(current);
959 acc = Semigroup::append(acc, first);
960 match step {
961 ControlFlow::Continue(next) => current = next,
962 ControlFlow::Break(b) => return Pair(acc, b),
963 }
964 }
965 }
966 }
967
968 #[document_type_parameters("The type of the first value in the pair.")]
969 impl<First: 'static> Foldable for PairFirstAppliedBrand<First> {
970 #[document_signature]
974 #[document_type_parameters(
976 "The lifetime of the values.",
977 "The brand of the cloneable function to use.",
978 "The type of the elements in the structure.",
979 "The type of the accumulator."
980 )]
981 #[document_parameters("The folding function.", "The initial value.", "The pair to fold.")]
983 #[document_returns("`func(a, initial)`.")]
985 #[document_examples]
987 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1001 func: impl Fn(A, B) -> B + 'a,
1002 initial: B,
1003 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1004 ) -> B
1005 where
1006 FnBrand: CloneableFn + 'a, {
1007 func(fa.1, initial)
1008 }
1009
1010 #[document_signature]
1014 #[document_type_parameters(
1016 "The lifetime of the values.",
1017 "The brand of the cloneable function to use.",
1018 "The type of the elements in the structure.",
1019 "The type of the accumulator."
1020 )]
1021 #[document_parameters(
1023 "The function to apply to the accumulator and each element.",
1024 "The initial value of the accumulator.",
1025 "The identity to fold."
1026 )]
1027 #[document_returns("`func(initial, a)`.")]
1029 #[document_examples]
1030 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1044 func: impl Fn(B, A) -> B + 'a,
1045 initial: B,
1046 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1047 ) -> B
1048 where
1049 FnBrand: CloneableFn + 'a, {
1050 func(initial, fa.1)
1051 }
1052
1053 #[document_signature]
1057 #[document_type_parameters(
1059 "The lifetime of the values.",
1060 "The brand of the cloneable function to use.",
1061 "The type of the elements in the structure.",
1062 "The type of the monoid."
1063 )]
1064 #[document_parameters("The mapping function.", "The pair to fold.")]
1066 #[document_returns("`func(a)`.")]
1068 #[document_examples]
1070 fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
1084 func: impl Fn(A) -> M + 'a,
1085 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1086 ) -> M
1087 where
1088 M: Monoid + 'a,
1089 FnBrand: CloneableFn + 'a, {
1090 func(fa.1)
1091 }
1092 }
1093
1094 #[document_type_parameters("The type of the first value in the pair.")]
1095 impl<First: Clone + 'static> Traversable for PairFirstAppliedBrand<First> {
1096 #[document_signature]
1100 #[document_type_parameters(
1102 "The lifetime of the values.",
1103 "The type of the elements in the traversable structure.",
1104 "The type of the elements in the resulting traversable structure.",
1105 "The applicative context."
1106 )]
1107 #[document_parameters(
1109 "The function to apply to each element, returning a value in an applicative context.",
1110 "The pair to traverse."
1111 )]
1112 #[document_returns("The pair wrapped in the applicative context.")]
1114 #[document_examples]
1115 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1129 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1130 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1131 ) -> 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>)>)
1132 where
1133 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1134 let Pair(first, second) = ta;
1135 F::map(move |b| Pair(first.clone(), b), func(second))
1136 }
1137
1138 #[document_signature]
1142 #[document_type_parameters(
1144 "The lifetime of the values.",
1145 "The type of the elements in the traversable structure.",
1146 "The applicative context."
1147 )]
1148 #[document_parameters("The pair containing the applicative value.")]
1150 #[document_returns("The pair wrapped in the applicative context.")]
1152 #[document_examples]
1154 fn sequence<'a, A: 'a + Clone, F: Applicative>(
1168 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>)>)
1169 ) -> 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>)>)
1170 where
1171 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1172 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
1173 let Pair(first, second) = ta;
1174 F::map(move |a| Pair(first.clone(), a), second)
1175 }
1176 }
1177
1178 impl_kind! {
1181 #[document_type_parameters("The type of the second value in the pair.")]
1182 impl<Second: 'static> for PairSecondAppliedBrand<Second> {
1183 type Of<'a, A: 'a>: 'a = Pair<A, Second>;
1184 }
1185 }
1186
1187 #[document_type_parameters("The type of the second value in the pair.")]
1188 impl<Second: 'static> Functor for PairSecondAppliedBrand<Second> {
1189 #[document_signature]
1193 #[document_type_parameters(
1195 "The lifetime of the values.",
1196 "The type of the first value.",
1197 "The type of the result of applying the function."
1198 )]
1199 #[document_parameters("The function to apply to the first value.", "The pair to map over.")]
1201 #[document_returns(
1203 "A new pair containing the result of applying the function to the first value."
1204 )]
1205 #[document_examples]
1207 fn map<'a, A: 'a, B: 'a>(
1218 func: impl Fn(A) -> B + 'a,
1219 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1220 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1221 fa.map_first(func)
1222 }
1223 }
1224
1225 #[document_type_parameters("The type of the second value in the pair.")]
1226 impl<Second: Clone + 'static> Lift for PairSecondAppliedBrand<Second>
1227 where
1228 Second: Semigroup,
1229 {
1230 #[document_signature]
1234 #[document_type_parameters(
1236 "The lifetime of the values.",
1237 "The type of the first first value.",
1238 "The type of the second first value.",
1239 "The type of the result first value."
1240 )]
1241 #[document_parameters(
1243 "The binary function to apply to the first values.",
1244 "The first pair.",
1245 "The second pair."
1246 )]
1247 #[document_returns(
1249 "A new pair where the first values are combined using `f` and the second values are combined using `Semigroup::append`."
1250 )]
1251 #[document_examples]
1252 fn lift2<'a, A, B, C>(
1270 func: impl Fn(A, B) -> C + 'a,
1271 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1272 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
1273 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
1274 where
1275 A: Clone + 'a,
1276 B: Clone + 'a,
1277 C: 'a, {
1278 Pair(func(fa.0, fb.0), Semigroup::append(fa.1, fb.1))
1279 }
1280 }
1281
1282 #[document_type_parameters("The type of the second value in the pair.")]
1283 impl<Second: Clone + 'static> Pointed for PairSecondAppliedBrand<Second>
1284 where
1285 Second: Monoid,
1286 {
1287 #[document_signature]
1291 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
1293 #[document_parameters("The value to wrap.")]
1295 #[document_returns("A pair containing `a` and the empty value of the second type.")]
1297 #[document_examples]
1299 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
1310 Pair(a, Monoid::empty())
1311 }
1312 }
1313
1314 #[document_type_parameters("The type of the second value in the pair.")]
1315 impl<Second: Clone + Semigroup + 'static> ApplyFirst for PairSecondAppliedBrand<Second> {}
1316
1317 #[document_type_parameters("The type of the second value in the pair.")]
1318 impl<Second: Clone + Semigroup + 'static> ApplySecond for PairSecondAppliedBrand<Second> {}
1319
1320 #[document_type_parameters("The type of the second value in the pair.")]
1321 impl<Second: Clone + 'static> Semiapplicative for PairSecondAppliedBrand<Second>
1322 where
1323 Second: Semigroup,
1324 {
1325 #[document_signature]
1329 #[document_type_parameters(
1331 "The lifetime of the values.",
1332 "The brand of the cloneable function wrapper.",
1333 "The type of the input value.",
1334 "The type of the output value."
1335 )]
1336 #[document_parameters(
1338 "The pair containing the function (in Err).",
1339 "The pair containing the value (in Err)."
1340 )]
1341 #[document_returns(
1343 "`Err(f(a))` if both are `Err`, otherwise the first success encountered."
1344 )]
1345 #[document_examples]
1346 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
1361 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
1362 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1363 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1364 Pair(ff.0(fa.0), Semigroup::append(ff.1, fa.1))
1365 }
1366 }
1367
1368 #[document_type_parameters("The type of the second value in the pair.")]
1369 impl<Second: Clone + 'static> Semimonad for PairSecondAppliedBrand<Second>
1370 where
1371 Second: Semigroup,
1372 {
1373 #[document_signature]
1377 #[document_type_parameters(
1379 "The lifetime of the values.",
1380 "The type of the result of the first computation.",
1381 "The type of the result of the second computation."
1382 )]
1383 #[document_parameters("The first result.", "The function to apply to the error value.")]
1385 #[document_returns(
1387 "The result of applying `f` to the error if `ma` is `Err`, otherwise the original success."
1388 )]
1389 #[document_examples]
1391 fn bind<'a, A: 'a, B: 'a>(
1408 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1409 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1410 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1411 ma.bind_first(func)
1412 }
1413 }
1414
1415 #[document_type_parameters("The type of the second value in the pair.")]
1417 impl<Second: Clone + 'static> MonadRec for PairSecondAppliedBrand<Second>
1418 where
1419 Second: Monoid,
1420 {
1421 #[document_signature]
1429 #[document_type_parameters(
1431 "The lifetime of the computation.",
1432 "The type of the initial value and loop state.",
1433 "The type of the result."
1434 )]
1435 #[document_parameters("The step function.", "The initial value.")]
1437 #[document_returns("A pair with the final result and the accumulated second value.")]
1439 #[document_examples]
1441 fn tail_rec_m<'a, A: 'a, B: 'a>(
1465 func: impl Fn(
1466 A,
1467 )
1468 -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1469 + 'a,
1470 initial: A,
1471 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1472 let mut acc: Second = Monoid::empty();
1473 let mut current = initial;
1474 loop {
1475 let Pair(step, second) = func(current);
1476 acc = Semigroup::append(acc, second);
1477 match step {
1478 ControlFlow::Continue(next) => current = next,
1479 ControlFlow::Break(b) => return Pair(b, acc),
1480 }
1481 }
1482 }
1483 }
1484
1485 #[document_type_parameters("The type of the second value in the pair.")]
1486 impl<Second: 'static> Foldable for PairSecondAppliedBrand<Second> {
1487 #[document_signature]
1491 #[document_type_parameters(
1493 "The lifetime of the values.",
1494 "The brand of the cloneable function to use.",
1495 "The type of the elements in the structure.",
1496 "The type of the accumulator."
1497 )]
1498 #[document_parameters("The folding function.", "The initial value.", "The result to fold.")]
1500 #[document_returns("`func(a, initial)` if `fa` is `Err(a)`, otherwise `initial`.")]
1502 #[document_examples]
1504 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1518 func: impl Fn(A, B) -> B + 'a,
1519 initial: B,
1520 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1521 ) -> B
1522 where
1523 FnBrand: CloneableFn + 'a, {
1524 func(fa.0, initial)
1525 }
1526
1527 #[document_signature]
1531 #[document_type_parameters(
1533 "The lifetime of the values.",
1534 "The brand of the cloneable function to use.",
1535 "The type of the elements in the structure.",
1536 "The type of the accumulator."
1537 )]
1538 #[document_parameters("The folding function.", "The initial value.", "The result to fold.")]
1540 #[document_returns("`func(initial, a)` if `fa` is `Err(a)`, otherwise `initial`.")]
1542 #[document_examples]
1544 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1558 func: impl Fn(B, A) -> B + 'a,
1559 initial: B,
1560 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1561 ) -> B
1562 where
1563 FnBrand: CloneableFn + 'a, {
1564 func(initial, fa.0)
1565 }
1566
1567 #[document_signature]
1571 #[document_type_parameters(
1573 "The lifetime of the values.",
1574 "The brand of the cloneable function to use.",
1575 "The type of the elements in the structure.",
1576 "The type of the monoid."
1577 )]
1578 #[document_parameters("The mapping function.", "The result to fold.")]
1580 #[document_returns("`func(a)` if `fa` is `Err(a)`, otherwise `M::empty()`.")]
1582 #[document_examples]
1584 fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
1601 func: impl Fn(A) -> M + 'a,
1602 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1603 ) -> M
1604 where
1605 M: Monoid + 'a,
1606 FnBrand: CloneableFn + 'a, {
1607 func(fa.0)
1608 }
1609 }
1610
1611 #[document_type_parameters("The type of the second value in the pair.")]
1612 impl<Second: Clone + 'static> Traversable for PairSecondAppliedBrand<Second> {
1613 #[document_signature]
1617 #[document_type_parameters(
1619 "The lifetime of the values.",
1620 "The type of the elements in the traversable structure.",
1621 "The type of the elements in the resulting traversable structure.",
1622 "The applicative context."
1623 )]
1624 #[document_parameters("The function to apply.", "The result to traverse.")]
1626 #[document_returns("The result wrapped in the applicative context.")]
1628 #[document_examples]
1630 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1644 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1645 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1646 ) -> 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>)>)
1647 where
1648 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1649 let Pair(first, second) = ta;
1650 F::map(move |b| Pair(b, second.clone()), func(first))
1651 }
1652
1653 #[document_signature]
1657 #[document_type_parameters(
1659 "The lifetime of the values.",
1660 "The type of the elements in the traversable structure.",
1661 "The applicative context."
1662 )]
1663 #[document_parameters("The result containing the applicative value.")]
1665 #[document_returns("The result wrapped in the applicative context.")]
1667 #[document_examples]
1669 fn sequence<'a, A: 'a + Clone, F: Applicative>(
1683 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>)>)
1684 ) -> 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>)>)
1685 where
1686 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1687 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
1688 let Pair(first, second) = ta;
1689 F::map(move |a| Pair(a, second.clone()), first)
1690 }
1691 }
1692}
1693pub use inner::*;
1694
1695#[cfg(test)]
1696mod tests {
1697 use {
1698 super::inner::*,
1699 crate::{
1700 brands::*,
1701 classes::{
1702 CloneableFn,
1703 bifunctor::*,
1704 },
1705 functions::*,
1706 },
1707 quickcheck_macros::quickcheck,
1708 };
1709
1710 #[test]
1714 fn test_bimap() {
1715 let x = Pair(1, 5);
1716 assert_eq!(bimap::<PairBrand, _, _, _, _>(|a| a + 1, |b| b * 2, x), Pair(2, 10));
1717 }
1718
1719 #[quickcheck]
1723 fn bifunctor_identity(
1724 first: String,
1725 second: i32,
1726 ) -> bool {
1727 let x = Pair(first, second);
1728 bimap::<PairBrand, _, _, _, _>(identity, identity, x.clone()) == x
1729 }
1730
1731 #[quickcheck]
1733 fn bifunctor_composition(
1734 first: i32,
1735 second: i32,
1736 ) -> bool {
1737 let x = Pair(first, second);
1738 let f = |x: i32| x.wrapping_add(1);
1739 let g = |x: i32| x.wrapping_mul(2);
1740 let h = |x: i32| x.wrapping_sub(1);
1741 let i = |x: i32| if x == 0 { 0 } else { x.wrapping_div(2) };
1742
1743 bimap::<PairBrand, _, _, _, _>(compose(f, g), compose(h, i), x)
1744 == bimap::<PairBrand, _, _, _, _>(f, h, bimap::<PairBrand, _, _, _, _>(g, i, x))
1745 }
1746
1747 #[quickcheck]
1751 fn functor_identity(
1752 first: String,
1753 second: i32,
1754 ) -> bool {
1755 let x = Pair(first, second);
1756 map::<PairFirstAppliedBrand<String>, _, _>(identity, x.clone()) == x
1757 }
1758
1759 #[quickcheck]
1761 fn functor_composition(
1762 first: String,
1763 second: i32,
1764 ) -> bool {
1765 let x = Pair(first, second);
1766 let f = |x: i32| x.wrapping_add(1);
1767 let g = |x: i32| x.wrapping_mul(2);
1768 map::<PairFirstAppliedBrand<String>, _, _>(compose(f, g), x.clone())
1769 == map::<PairFirstAppliedBrand<String>, _, _>(
1770 f,
1771 map::<PairFirstAppliedBrand<String>, _, _>(g, x),
1772 )
1773 }
1774
1775 #[quickcheck]
1779 fn applicative_identity(
1780 first: String,
1781 second: i32,
1782 ) -> bool {
1783 let v = Pair(first, second);
1784 apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1785 pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(identity)),
1786 v.clone(),
1787 ) == v
1788 }
1789
1790 #[quickcheck]
1792 fn applicative_homomorphism(x: i32) -> bool {
1793 let f = |x: i32| x.wrapping_mul(2);
1794 apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1795 pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(f)),
1796 pure::<PairFirstAppliedBrand<String>, _>(x),
1797 ) == pure::<PairFirstAppliedBrand<String>, _>(f(x))
1798 }
1799
1800 #[quickcheck]
1802 fn applicative_composition(
1803 w_first: String,
1804 w_second: i32,
1805 u_seed: i32,
1806 v_seed: i32,
1807 ) -> bool {
1808 let w = Pair(w_first, w_second);
1809
1810 let u_fn = <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_add(u_seed));
1811 let u = pure::<PairFirstAppliedBrand<String>, _>(u_fn);
1812
1813 let v_fn = <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_mul(v_seed));
1814 let v = pure::<PairFirstAppliedBrand<String>, _>(v_fn);
1815
1816 let vw = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(v.clone(), w.clone());
1818 let rhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(u.clone(), vw);
1819
1820 let compose_fn = <RcFnBrand as CloneableFn>::new(|f: std::rc::Rc<dyn Fn(i32) -> i32>| {
1822 let f = f.clone();
1823 <RcFnBrand as CloneableFn>::new(move |g: std::rc::Rc<dyn Fn(i32) -> i32>| {
1824 let f = f.clone();
1825 let g = g.clone();
1826 <RcFnBrand as CloneableFn>::new(move |x| f(g(x)))
1827 })
1828 });
1829
1830 let pure_compose = pure::<PairFirstAppliedBrand<String>, _>(compose_fn);
1831 let u_applied = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(pure_compose, u);
1832 let uv = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(u_applied, v);
1833 let lhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(uv, w);
1834
1835 lhs == rhs
1836 }
1837
1838 #[quickcheck]
1840 fn applicative_interchange(
1841 y: i32,
1842 u_seed: i32,
1843 ) -> bool {
1844 let f = move |x: i32| x.wrapping_mul(u_seed);
1846 let u = pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(f));
1847
1848 let lhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1849 u.clone(),
1850 pure::<PairFirstAppliedBrand<String>, _>(y),
1851 );
1852
1853 let rhs_fn =
1854 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1855 let rhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1856 pure::<PairFirstAppliedBrand<String>, _>(rhs_fn),
1857 u,
1858 );
1859
1860 lhs == rhs
1861 }
1862
1863 #[quickcheck]
1867 fn monad_left_identity(a: i32) -> bool {
1868 let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
1869 bind::<PairFirstAppliedBrand<String>, _, _>(pure::<PairFirstAppliedBrand<String>, _>(a), f)
1870 == f(a)
1871 }
1872
1873 #[quickcheck]
1875 fn monad_right_identity(
1876 first: String,
1877 second: i32,
1878 ) -> bool {
1879 let m = Pair(first, second);
1880 bind::<PairFirstAppliedBrand<String>, _, _>(
1881 m.clone(),
1882 pure::<PairFirstAppliedBrand<String>, _>,
1883 ) == m
1884 }
1885
1886 #[quickcheck]
1888 fn monad_associativity(
1889 first: String,
1890 second: i32,
1891 ) -> bool {
1892 let m = Pair(first, second);
1893 let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
1894 let g = |x: i32| Pair("g".to_string(), x.wrapping_add(1));
1895 bind::<PairFirstAppliedBrand<String>, _, _>(
1896 bind::<PairFirstAppliedBrand<String>, _, _>(m.clone(), f),
1897 g,
1898 ) == bind::<PairFirstAppliedBrand<String>, _, _>(m, |x| {
1899 bind::<PairFirstAppliedBrand<String>, _, _>(f(x), g)
1900 })
1901 }
1902
1903 #[quickcheck]
1907 fn monad_rec_first_applied_identity(x: i32) -> bool {
1908 use {
1909 crate::classes::monad_rec::tail_rec_m,
1910 core::ops::ControlFlow,
1911 };
1912 tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
1913 |a| Pair(String::new(), ControlFlow::Break(a)),
1914 x,
1915 ) == Pair(String::new(), x)
1916 }
1917
1918 #[test]
1920 fn monad_rec_first_applied_accumulation() {
1921 use {
1922 crate::classes::monad_rec::tail_rec_m,
1923 core::ops::ControlFlow,
1924 };
1925 let result = tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
1926 |n: i32| {
1927 if n < 3 {
1928 Pair(format!("{n},"), ControlFlow::Continue(n + 1))
1929 } else {
1930 Pair(format!("{n}"), ControlFlow::Break(n))
1931 }
1932 },
1933 0,
1934 );
1935 assert_eq!(result, Pair("0,1,2,3".to_string(), 3));
1936 }
1937
1938 #[test]
1940 fn monad_rec_first_applied_stack_safety() {
1941 use {
1942 crate::classes::monad_rec::tail_rec_m,
1943 core::ops::ControlFlow,
1944 };
1945 let iterations: i64 = 200_000;
1946 let result = tail_rec_m::<PairFirstAppliedBrand<Vec<()>>, _, _>(
1947 |acc| {
1948 if acc < iterations {
1949 Pair(vec![], ControlFlow::Continue(acc + 1))
1950 } else {
1951 Pair(vec![], ControlFlow::Break(acc))
1952 }
1953 },
1954 0i64,
1955 );
1956 assert_eq!(result, Pair(vec![], iterations));
1957 }
1958
1959 #[quickcheck]
1963 fn monad_rec_second_applied_identity(x: i32) -> bool {
1964 use {
1965 crate::classes::monad_rec::tail_rec_m,
1966 core::ops::ControlFlow,
1967 };
1968 tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
1969 |a| Pair(ControlFlow::Break(a), String::new()),
1970 x,
1971 ) == Pair(x, String::new())
1972 }
1973
1974 #[test]
1976 fn monad_rec_second_applied_accumulation() {
1977 use {
1978 crate::classes::monad_rec::tail_rec_m,
1979 core::ops::ControlFlow,
1980 };
1981 let result = tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
1982 |n: i32| {
1983 if n < 3 {
1984 Pair(ControlFlow::Continue(n + 1), format!("{n},"))
1985 } else {
1986 Pair(ControlFlow::Break(n), format!("{n}"))
1987 }
1988 },
1989 0,
1990 );
1991 assert_eq!(result, Pair(3, "0,1,2,3".to_string()));
1992 }
1993
1994 #[test]
1996 fn monad_rec_second_applied_stack_safety() {
1997 use {
1998 crate::classes::monad_rec::tail_rec_m,
1999 core::ops::ControlFlow,
2000 };
2001 let iterations: i64 = 200_000;
2002 let result = tail_rec_m::<PairSecondAppliedBrand<Vec<()>>, _, _>(
2003 |acc| {
2004 if acc < iterations {
2005 Pair(ControlFlow::Continue(acc + 1), vec![])
2006 } else {
2007 Pair(ControlFlow::Break(acc), vec![])
2008 }
2009 },
2010 0i64,
2011 );
2012 assert_eq!(result, Pair(iterations, vec![]));
2013 }
2014}