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::<RcFnBrand, Tuple1Brand, _, _>(
730 pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(identity)),
731 v,
732 ) == v
733 }
734
735 #[quickcheck]
737 fn applicative_homomorphism(x: i32) -> bool {
738 let f = |x: i32| x.wrapping_mul(2);
739 apply::<RcFnBrand, Tuple1Brand, _, _>(
740 pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(f)),
741 pure::<Tuple1Brand, _>(x),
742 ) == pure::<Tuple1Brand, _>(f(x))
743 }
744
745 #[quickcheck]
747 fn applicative_composition(
748 w: i32,
749 u_val: i32,
750 v_val: i32,
751 ) -> bool {
752 let w = (w,);
753 let v_fn = move |x: i32| x.wrapping_mul(v_val);
754 let u_fn = move |x: i32| x.wrapping_add(u_val);
755
756 let v = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(v_fn));
757 let u = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(u_fn));
758
759 let vw = apply::<RcFnBrand, Tuple1Brand, _, _>(v.clone(), w);
761 let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), vw);
762
763 let composed = move |x| u_fn(v_fn(x));
765 let uv = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(composed));
766
767 let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(uv, w);
768
769 lhs == rhs
770 }
771
772 #[quickcheck]
774 fn applicative_interchange(y: i32) -> bool {
775 let f = |x: i32| x.wrapping_mul(2);
777 let u = pure::<Tuple1Brand, _>(<RcFnBrand as LiftFn>::new(f));
778
779 let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), pure::<Tuple1Brand, _>(y));
780
781 let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
782 let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(pure::<Tuple1Brand, _>(rhs_fn), u);
783
784 lhs == rhs
785 }
786
787 #[quickcheck]
791 fn monad_left_identity(a: i32) -> bool {
792 let f = |x: i32| (x.wrapping_mul(2),);
793 explicit::bind::<Tuple1Brand, _, _, _, _>(pure::<Tuple1Brand, _>(a), f) == f(a)
794 }
795
796 #[quickcheck]
798 fn monad_right_identity(m: i32) -> bool {
799 let m = (m,);
800 explicit::bind::<Tuple1Brand, _, _, _, _>(m, pure::<Tuple1Brand, _>) == m
801 }
802
803 #[quickcheck]
805 fn monad_associativity(m: i32) -> bool {
806 let m = (m,);
807 let f = |x: i32| (x.wrapping_mul(2),);
808 let g = |x: i32| (x.wrapping_add(1),);
809 explicit::bind::<Tuple1Brand, _, _, _, _>(
810 explicit::bind::<Tuple1Brand, _, _, _, _>(m, f),
811 g,
812 ) == explicit::bind::<Tuple1Brand, _, _, _, _>(m, |x| {
813 explicit::bind::<Tuple1Brand, _, _, _, _>(f(x), g)
814 })
815 }
816
817 #[test]
821 fn map_test() {
822 assert_eq!(explicit::map::<Tuple1Brand, _, _, _, _>(|x: i32| x + 1, (1,)), (2,));
823 }
824
825 #[test]
827 fn bind_test() {
828 assert_eq!(explicit::bind::<Tuple1Brand, _, _, _, _>((1,), |x| (x + 1,)), (2,));
829 }
830
831 #[test]
833 fn fold_right_test() {
834 assert_eq!(
835 crate::functions::explicit::fold_right::<RcFnBrand, Tuple1Brand, _, _, _, _>(
836 |x: i32, acc| x + acc,
837 0,
838 (1,)
839 ),
840 1
841 );
842 }
843
844 #[test]
846 fn fold_left_test() {
847 assert_eq!(
848 crate::functions::explicit::fold_left::<RcFnBrand, Tuple1Brand, _, _, _, _>(
849 |acc, x: i32| acc + x,
850 0,
851 (1,)
852 ),
853 1
854 );
855 }
856
857 #[test]
859 fn traverse_test() {
860 assert_eq!(
861 crate::classes::traversable::traverse::<Tuple1Brand, _, _, OptionBrand>(
862 |x: i32| Some(x + 1),
863 (1,)
864 ),
865 Some((2,))
866 );
867 }
868
869 #[quickcheck]
873 fn monad_rec_identity(x: i32) -> bool {
874 use {
875 crate::classes::monad_rec::tail_rec_m,
876 core::ops::ControlFlow,
877 };
878 tail_rec_m::<Tuple1Brand, _, _>(|a| (ControlFlow::Break(a),), x) == (x,)
879 }
880
881 #[test]
883 fn monad_rec_sum_range() {
884 use {
885 crate::classes::monad_rec::tail_rec_m,
886 core::ops::ControlFlow,
887 };
888 let result = tail_rec_m::<Tuple1Brand, _, _>(
889 |(n, acc)| {
890 if n == 0 {
891 (ControlFlow::Break(acc),)
892 } else {
893 (ControlFlow::Continue((n - 1, acc + n)),)
894 }
895 },
896 (100i64, 0i64),
897 );
898 assert_eq!(result, (5050,));
899 }
900
901 #[test]
903 fn monad_rec_stack_safety() {
904 use {
905 crate::classes::monad_rec::tail_rec_m,
906 core::ops::ControlFlow,
907 };
908 let iterations: i64 = 200_000;
909 let result = tail_rec_m::<Tuple1Brand, _, _>(
910 |acc| {
911 if acc < iterations {
912 (ControlFlow::Continue(acc + 1),)
913 } else {
914 (ControlFlow::Break(acc),)
915 }
916 },
917 0i64,
918 );
919 assert_eq!(result, (iterations,));
920 }
921}