1#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::{
9 Apply,
10 brands::Tuple1Brand,
11 classes::*,
12 dispatch::Ref,
13 impl_kind,
14 kinds::*,
15 },
16 core::ops::ControlFlow,
17 fp_macros::*,
18 };
19
20 impl_kind! {
21 for Tuple1Brand {
22 type Of<A> = (A,);
23 }
24 }
25
26 impl_kind! {
27 for Tuple1Brand {
28 type Of<'a, A: 'a>: 'a = (A,);
29 }
30 }
31
32 impl Functor for Tuple1Brand {
33 #[document_signature]
37 #[document_type_parameters(
39 "The lifetime of the value.",
40 "The type of the value inside the tuple.",
41 "The type of the result of applying the function."
42 )]
43 #[document_parameters("The function to apply.", "The tuple to map over.")]
45 #[document_returns("A new 1-tuple containing the result of applying the function.")]
47 #[document_examples]
49 fn map<'a, A: 'a, B: 'a>(
61 func: impl Fn(A) -> B + 'a,
62 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
63 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
64 (func(fa.0),)
65 }
66 }
67
68 impl Lift for Tuple1Brand {
69 #[document_signature]
73 #[document_type_parameters(
75 "The lifetime of the values.",
76 "The type of the first tuple's value.",
77 "The type of the second tuple's value.",
78 "The return type of the function."
79 )]
80 #[document_parameters(
82 "The binary function to apply.",
83 "The first tuple.",
84 "The second tuple."
85 )]
86 #[document_returns("A new 1-tuple containing the result of applying the function.")]
88 #[document_examples]
89 fn lift2<'a, A, B, C>(
102 func: impl Fn(A, B) -> C + 'a,
103 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
104 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
105 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
106 where
107 A: 'a,
108 B: 'a,
109 C: 'a, {
110 (func(fa.0, fb.0),)
111 }
112 }
113
114 impl Pointed for Tuple1Brand {
115 #[document_signature]
119 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
121 #[document_parameters("The value to wrap.")]
123 #[document_returns("A 1-tuple containing the value.")]
125 #[document_examples]
127 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
138 (a,)
139 }
140 }
141
142 impl ApplyFirst for Tuple1Brand {}
143 impl ApplySecond for Tuple1Brand {}
144
145 impl Semiapplicative for Tuple1Brand {
146 #[document_signature]
150 #[document_type_parameters(
152 "The lifetime of the values.",
153 "The brand of the cloneable function wrapper.",
154 "The type of the input value.",
155 "The type of the output value."
156 )]
157 #[document_parameters(
159 "The tuple containing the function.",
160 "The tuple containing the value."
161 )]
162 #[document_returns("A new 1-tuple containing the result of applying the function.")]
164 #[document_examples]
165 fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
178 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
179 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
180 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
181 (ff.0(fa.0),)
182 }
183 }
184
185 impl Semimonad for Tuple1Brand {
186 #[document_signature]
190 #[document_type_parameters(
192 "The lifetime of the values.",
193 "The type of the result of the first computation.",
194 "The type of the result of the second computation."
195 )]
196 #[document_parameters(
198 "The first tuple.",
199 "The function to apply to the value inside the tuple."
200 )]
201 #[document_returns("The result of applying `f` to the value.")]
203 #[document_examples]
204 fn bind<'a, A: 'a, B: 'a>(
216 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
217 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
218 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
219 func(ma.0)
220 }
221 }
222
223 impl Foldable for Tuple1Brand {
224 #[document_signature]
228 #[document_type_parameters(
230 "The lifetime of the values.",
231 "The brand of the cloneable function to use.",
232 "The type of the elements in the structure.",
233 "The type of the accumulator."
234 )]
235 #[document_parameters(
237 "The function to apply to each element and the accumulator.",
238 "The initial value of the accumulator.",
239 "The tuple to fold."
240 )]
241 #[document_returns("The final accumulator value.")]
243 #[document_examples]
244 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
256 func: impl Fn(A, B) -> B + 'a,
257 initial: B,
258 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
259 ) -> B
260 where
261 FnBrand: CloneFn + 'a, {
262 func(fa.0, initial)
263 }
264
265 #[document_signature]
269 #[document_type_parameters(
271 "The lifetime of the values.",
272 "The brand of the cloneable function to use.",
273 "The type of the elements in the structure.",
274 "The type of the accumulator."
275 )]
276 #[document_parameters(
278 "The function to apply to the accumulator and each element.",
279 "The initial value of the accumulator.",
280 "The tuple to fold."
281 )]
282 #[document_returns("The final accumulator value.")]
284 #[document_examples]
285 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
297 func: impl Fn(B, A) -> B + 'a,
298 initial: B,
299 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
300 ) -> B
301 where
302 FnBrand: CloneFn + 'a, {
303 func(initial, fa.0)
304 }
305
306 #[document_signature]
310 #[document_type_parameters(
312 "The lifetime of the values.",
313 "The brand of the cloneable function to use.",
314 "The type of the elements in the structure.",
315 "The type of the monoid."
316 )]
317 #[document_parameters(
319 "The thread-safe function to map each element to a monoid.",
320 "The tuple to fold."
321 )]
322 #[document_returns("The monoid value.")]
324 #[document_examples]
325 fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
337 func: impl Fn(A) -> M + 'a,
338 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
339 ) -> M
340 where
341 M: Monoid + 'a,
342 FnBrand: CloneFn + 'a, {
343 func(fa.0)
344 }
345 }
346
347 impl Traversable for Tuple1Brand {
348 #[document_signature]
352 #[document_type_parameters(
354 "The lifetime of the values.",
355 "The type of the elements in the traversable structure.",
356 "The type of the elements in the resulting traversable structure.",
357 "The applicative context."
358 )]
359 #[document_parameters(
361 "The function to apply to each element, returning a value in an applicative context.",
362 "The tuple to traverse."
363 )]
364 #[document_returns("The 1-tuple wrapped in the applicative context.")]
366 #[document_examples]
367 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
380 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
381 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
382 ) -> 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>)>)
383 where
384 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
385 F::map(|b| (b,), func(ta.0))
386 }
387
388 #[document_signature]
392 #[document_type_parameters(
394 "The lifetime of the values.",
395 "The type of the elements in the traversable structure.",
396 "The applicative context."
397 )]
398 #[document_parameters("The tuple containing the applicative value.")]
400 #[document_returns("The 1-tuple wrapped in the applicative context.")]
402 #[document_examples]
404 fn sequence<'a, A: 'a + Clone, F: Applicative>(
416 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>)>)
417 ) -> 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>)>)
418 where
419 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
420 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
421 F::map(|a| (a,), ta.0)
422 }
423 }
424
425 impl RefFunctor for Tuple1Brand {
428 #[document_signature]
430 #[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
431 #[document_parameters("The function.", "The tuple.")]
432 #[document_returns("A new 1-tuple containing the result.")]
433 #[document_examples]
434 fn ref_map<'a, A: 'a, B: 'a>(
443 func: impl Fn(&A) -> B + 'a,
444 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
445 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
446 (func(&fa.0),)
447 }
448 }
449
450 impl RefFoldable for Tuple1Brand {
451 #[document_signature]
453 #[document_type_parameters(
454 "The lifetime.",
455 "The brand.",
456 "The element type.",
457 "The monoid type."
458 )]
459 #[document_parameters("The mapping function.", "The tuple.")]
460 #[document_returns("The monoid value.")]
461 #[document_examples]
462 fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
473 func: impl Fn(&A) -> M + 'a,
474 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
475 ) -> M
476 where
477 FnBrand: LiftFn + 'a,
478 M: Monoid + 'a, {
479 func(&fa.0)
480 }
481 }
482
483 impl RefTraversable for Tuple1Brand {
484 #[document_signature]
486 #[document_type_parameters(
487 "The lifetime.",
488 "The brand.",
489 "The input type.",
490 "The output type.",
491 "The applicative."
492 )]
493 #[document_parameters("The function.", "The tuple.")]
494 #[document_returns("The traversed result.")]
495 #[document_examples]
496 fn ref_traverse<'a, FnBrand, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
509 func: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
510 ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
511 ) -> 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>)>)
512 where
513 FnBrand: LiftFn + 'a,
514 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
515 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
516 F::map(|b| (b,), func(&ta.0))
517 }
518 }
519
520 impl RefPointed for Tuple1Brand {
521 #[document_signature]
523 #[document_type_parameters("The lifetime.", "The value type.")]
524 #[document_parameters("The reference to wrap.")]
525 #[document_returns("A 1-tuple containing a clone of the value.")]
526 #[document_examples]
527 fn ref_pure<'a, A: Clone + 'a>(
539 a: &A
540 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
541 (a.clone(),)
542 }
543 }
544
545 impl RefLift for Tuple1Brand {
546 #[document_signature]
548 #[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
549 #[document_parameters("The binary function.", "The first tuple.", "The second tuple.")]
550 #[document_returns("The combined 1-tuple.")]
551 #[document_examples]
552 fn ref_lift2<'a, A: 'a, B: 'a, C: 'a>(
564 func: impl Fn(&A, &B) -> C + 'a,
565 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
566 fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
567 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
568 (func(&fa.0, &fb.0),)
569 }
570 }
571
572 impl RefSemiapplicative for Tuple1Brand {
573 #[document_signature]
575 #[document_type_parameters(
576 "The lifetime.",
577 "The function brand.",
578 "The input type.",
579 "The output type."
580 )]
581 #[document_parameters(
582 "The tuple containing the function.",
583 "The tuple containing the value."
584 )]
585 #[document_returns("A 1-tuple containing the result.")]
586 #[document_examples]
587 fn ref_apply<'a, FnBrand: 'a + CloneFn<Ref>, A: 'a, B: 'a>(
600 ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn<Ref>>::Of<'a, A, B>>),
601 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
602 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
603 ((*ff.0)(&fa.0),)
604 }
605 }
606
607 impl RefSemimonad for Tuple1Brand {
608 #[document_signature]
610 #[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
611 #[document_parameters("The input tuple.", "The function to apply by reference.")]
612 #[document_returns("The resulting 1-tuple.")]
613 #[document_examples]
614 fn ref_bind<'a, A: 'a, B: 'a>(
626 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
627 f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
628 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
629 f(&fa.0)
630 }
631 }
632
633 impl MonadRec for Tuple1Brand {
634 #[document_signature]
639 #[document_type_parameters(
641 "The lifetime of the computation.",
642 "The type of the initial value and loop state.",
643 "The type of the result."
644 )]
645 #[document_parameters("The step function.", "The initial value.")]
647 #[document_returns("A 1-tuple containing the result of the computation.")]
649 #[document_examples]
651 fn tail_rec_m<'a, A: 'a, B: 'a>(
671 func: impl Fn(
672 A,
673 )
674 -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
675 + 'a,
676 initial: A,
677 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
678 let mut current = initial;
679 loop {
680 match func(current).0 {
681 ControlFlow::Continue(next) => current = next,
682 ControlFlow::Break(b) => return (b,),
683 }
684 }
685 }
686 }
687}
688
689#[cfg(test)]
690mod tests {
691
692 use {
693 crate::{
694 brands::*,
695 classes::*,
696 functions::*,
697 },
698 quickcheck_macros::quickcheck,
699 };
700
701 #[quickcheck]
705 fn functor_identity(x: i32) -> bool {
706 let x = (x,);
707 explicit::map::<Tuple1Brand, _, _, _, _>(identity, x) == x
708 }
709
710 #[quickcheck]
712 fn functor_composition(x: i32) -> bool {
713 let x = (x,);
714 let f = |x: i32| x.wrapping_add(1);
715 let g = |x: i32| x.wrapping_mul(2);
716 explicit::map::<Tuple1Brand, _, _, _, _>(compose(f, g), x)
717 == explicit::map::<Tuple1Brand, _, _, _, _>(
718 f,
719 explicit::map::<Tuple1Brand, _, _, _, _>(g, x),
720 )
721 }
722
723 #[quickcheck]
727 fn applicative_identity(v: i32) -> bool {
728 let v = (v,);
729 apply(pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(identity)), v) == v
730 }
731
732 #[quickcheck]
734 fn applicative_homomorphism(x: i32) -> bool {
735 let f = |x: i32| x.wrapping_mul(2);
736 apply(pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(f)), pure::<Tuple1Brand, _>(x))
737 == pure::<Tuple1Brand, _>(f(x))
738 }
739
740 #[quickcheck]
742 fn applicative_composition(
743 w: i32,
744 u_val: i32,
745 v_val: i32,
746 ) -> bool {
747 let w = (w,);
748 let v_fn = move |x: i32| x.wrapping_mul(v_val);
749 let u_fn = move |x: i32| x.wrapping_add(u_val);
750
751 let v = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(v_fn));
752 let u = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(u_fn));
753
754 let vw = apply(v.clone(), w);
756 let rhs = apply(u.clone(), vw);
757
758 let composed = move |x| u_fn(v_fn(x));
760 let uv = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(composed));
761
762 let lhs = apply(uv, w);
763
764 lhs == rhs
765 }
766
767 #[quickcheck]
769 fn applicative_interchange(y: i32) -> bool {
770 let f = |x: i32| x.wrapping_mul(2);
772 let u = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(f));
773
774 let lhs = apply(u.clone(), pure::<Tuple1Brand, _>(y));
775
776 let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
777 let rhs = apply(pure::<Tuple1Brand, _>(rhs_fn), u);
778
779 lhs == rhs
780 }
781
782 #[quickcheck]
786 fn monad_left_identity(a: i32) -> bool {
787 let f = |x: i32| (x.wrapping_mul(2),);
788 explicit::bind::<Tuple1Brand, _, _, _, _>(pure::<Tuple1Brand, _>(a), f) == f(a)
789 }
790
791 #[quickcheck]
793 fn monad_right_identity(m: i32) -> bool {
794 let m = (m,);
795 explicit::bind::<Tuple1Brand, _, _, _, _>(m, pure::<Tuple1Brand, _>) == m
796 }
797
798 #[quickcheck]
800 fn monad_associativity(m: i32) -> bool {
801 let m = (m,);
802 let f = |x: i32| (x.wrapping_mul(2),);
803 let g = |x: i32| (x.wrapping_add(1),);
804 explicit::bind::<Tuple1Brand, _, _, _, _>(
805 explicit::bind::<Tuple1Brand, _, _, _, _>(m, f),
806 g,
807 ) == explicit::bind::<Tuple1Brand, _, _, _, _>(m, |x| {
808 explicit::bind::<Tuple1Brand, _, _, _, _>(f(x), g)
809 })
810 }
811
812 #[test]
816 fn map_test() {
817 assert_eq!(explicit::map::<Tuple1Brand, _, _, _, _>(|x: i32| x + 1, (1,)), (2,));
818 }
819
820 #[test]
822 fn bind_test() {
823 assert_eq!(explicit::bind::<Tuple1Brand, _, _, _, _>((1,), |x| (x + 1,)), (2,));
824 }
825
826 #[test]
828 fn fold_right_test() {
829 assert_eq!(
830 crate::functions::explicit::fold_right::<RcFnBrand, Tuple1Brand, _, _, _, _>(
831 |x: i32, acc| x + acc,
832 0,
833 (1,)
834 ),
835 1
836 );
837 }
838
839 #[test]
841 fn fold_left_test() {
842 assert_eq!(
843 crate::functions::explicit::fold_left::<RcFnBrand, Tuple1Brand, _, _, _, _>(
844 |acc, x: i32| acc + x,
845 0,
846 (1,)
847 ),
848 1
849 );
850 }
851
852 #[test]
854 fn traverse_test() {
855 assert_eq!(
856 crate::classes::traversable::traverse::<Tuple1Brand, _, _, OptionBrand>(
857 |x: i32| Some(x + 1),
858 (1,)
859 ),
860 Some((2,))
861 );
862 }
863
864 #[quickcheck]
868 fn monad_rec_identity(x: i32) -> bool {
869 use {
870 crate::classes::monad_rec::tail_rec_m,
871 core::ops::ControlFlow,
872 };
873 tail_rec_m::<Tuple1Brand, _, _>(|a| (ControlFlow::Break(a),), x) == (x,)
874 }
875
876 #[test]
878 fn monad_rec_sum_range() {
879 use {
880 crate::classes::monad_rec::tail_rec_m,
881 core::ops::ControlFlow,
882 };
883 let result = tail_rec_m::<Tuple1Brand, _, _>(
884 |(n, acc)| {
885 if n == 0 {
886 (ControlFlow::Break(acc),)
887 } else {
888 (ControlFlow::Continue((n - 1, acc + n)),)
889 }
890 },
891 (100i64, 0i64),
892 );
893 assert_eq!(result, (5050,));
894 }
895
896 #[test]
898 fn monad_rec_stack_safety() {
899 use {
900 crate::classes::monad_rec::tail_rec_m,
901 core::ops::ControlFlow,
902 };
903 let iterations: i64 = 200_000;
904 let result = tail_rec_m::<Tuple1Brand, _, _>(
905 |acc| {
906 if acc < iterations {
907 (ControlFlow::Continue(acc + 1),)
908 } else {
909 (ControlFlow::Break(acc),)
910 }
911 },
912 0i64,
913 );
914 assert_eq!(result, (iterations,));
915 }
916}