1#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::{
9 Apply,
10 brands::IdentityBrand,
11 classes::{
12 Applicative,
13 ApplyFirst,
14 ApplySecond,
15 CloneableFn,
16 Foldable,
17 Functor,
18 Lift,
19 Monoid,
20 ParFoldable,
21 Pointed,
22 Semiapplicative,
23 Semimonad,
24 SendCloneableFn,
25 Traversable,
26 },
27 impl_kind,
28 kinds::*,
29 },
30 fp_macros::*,
31 };
32
33 #[document_type_parameters("The type of the wrapped value.")]
47 #[document_fields("The wrapped value.")]
49 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
51 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
52 pub struct Identity<A>(pub A);
53
54 impl_kind! {
55 for IdentityBrand {
56 type Of<'a, A: 'a>: 'a = Identity<A>;
57 }
58 }
59
60 #[document_type_parameters("The type of the wrapped value.")]
61 #[document_parameters("The identity instance.")]
62 impl<A> Identity<A> {
63 #[document_signature]
68 #[document_type_parameters("The type of the result of applying the function.")]
70 #[document_parameters("The function to apply.")]
72 #[document_returns("A new identity containing the result of applying the function.")]
74 #[document_examples]
76 pub fn map<B>(
85 self,
86 f: impl FnOnce(A) -> B,
87 ) -> Identity<B> {
88 Identity(f(self.0))
89 }
90
91 #[document_signature]
95 #[document_type_parameters(
97 "The type of the other identity's value.",
98 "The return type of the function."
99 )]
100 #[document_parameters("The other identity.", "The binary function to apply.")]
102 #[document_returns("A new identity containing the result of applying the function.")]
104 #[document_examples]
106 pub fn lift2<B, C>(
116 self,
117 other: Identity<B>,
118 f: impl FnOnce(A, B) -> C,
119 ) -> Identity<C> {
120 Identity(f(self.0, other.0))
121 }
122
123 #[document_signature]
127 #[document_type_parameters("The return type of the wrapped function.")]
129 #[document_parameters("The identity containing the function.")]
131 #[document_returns("A new identity containing the result.")]
133 #[document_examples]
135 pub fn apply<B>(
145 self,
146 ff: Identity<impl FnOnce(A) -> B>,
147 ) -> Identity<B> {
148 Identity(ff.0(self.0))
149 }
150
151 #[document_signature]
156 #[document_type_parameters("The type of the result of the chained computation.")]
158 #[document_parameters("The function to apply to the value inside the identity.")]
160 #[document_returns("The result of applying `f` to the value.")]
162 #[document_examples]
164 pub fn bind<B>(
173 self,
174 f: impl FnOnce(A) -> Identity<B>,
175 ) -> Identity<B> {
176 f(self.0)
177 }
178
179 #[document_signature]
183 #[document_type_parameters("The type of the accumulator.")]
185 #[document_parameters(
187 "The function to apply to the element and the accumulator.",
188 "The initial value of the accumulator."
189 )]
190 #[document_returns("The final accumulator value.")]
192 #[document_examples]
194 pub fn fold_right<B>(
203 self,
204 f: impl FnOnce(A, B) -> B,
205 initial: B,
206 ) -> B {
207 f(self.0, initial)
208 }
209
210 #[document_signature]
214 #[document_type_parameters("The type of the accumulator.")]
216 #[document_parameters(
218 "The function to apply to the accumulator and the element.",
219 "The initial value of the accumulator."
220 )]
221 #[document_returns("The final accumulator value.")]
223 #[document_examples]
225 pub fn fold_left<B>(
234 self,
235 f: impl FnOnce(B, A) -> B,
236 initial: B,
237 ) -> B {
238 f(initial, self.0)
239 }
240
241 #[document_signature]
245 #[document_type_parameters("The monoid type.")]
247 #[document_parameters("The mapping function.")]
249 #[document_returns("The monoid value.")]
251 #[document_examples]
253 pub fn fold_map<M>(
262 self,
263 f: impl FnOnce(A) -> M,
264 ) -> M {
265 f(self.0)
266 }
267 }
268
269 #[document_type_parameters("The lifetime of the values.", "The type of the wrapped value.")]
270 #[document_parameters("The identity instance.")]
271 impl<'a, A: 'a> Identity<A> {
272 #[document_signature]
276 #[document_type_parameters(
278 "The type of the elements in the resulting identity.",
279 "The applicative context."
280 )]
281 #[document_parameters(
283 "The function to apply, returning a value in an applicative context."
284 )]
285 #[document_returns("The identity wrapped in the applicative context.")]
287 #[document_examples]
289 pub fn traverse<B: 'a + Clone, F: Applicative>(
301 self,
302 f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
303 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<B>>)
304 where
305 Identity<B>: Clone, {
306 F::map(|b| Identity(b), f(self.0))
307 }
308
309 #[document_signature]
313 #[document_type_parameters(
315 "The inner type wrapped in the applicative context.",
316 "The applicative context."
317 )]
318 #[document_returns("The identity wrapped in the applicative context.")]
320 #[document_examples]
322 pub fn sequence<InnerA: 'a + Clone, F: Applicative>(
334 self
335 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<InnerA>>)
336 where
337 A: Into<Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, InnerA>)>,
338 Identity<InnerA>: Clone, {
339 F::map(|a| Identity(a), self.0.into())
340 }
341 }
342
343 impl Functor for IdentityBrand {
344 #[document_signature]
348 #[document_type_parameters(
350 "The lifetime of the value.",
351 "The type of the value inside the identity.",
352 "The type of the result of applying the function."
353 )]
354 #[document_parameters("The function to apply.", "The identity to map over.")]
356 #[document_returns("A new identity containing the result of applying the function.")]
358 #[document_examples]
360 fn map<'a, A: 'a, B: 'a>(
373 func: impl Fn(A) -> B + 'a,
374 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
375 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
376 fa.map(func)
377 }
378 }
379
380 impl Lift for IdentityBrand {
381 #[document_signature]
385 #[document_type_parameters(
387 "The lifetime of the values.",
388 "The type of the first identity's value.",
389 "The type of the second identity's value.",
390 "The return type of the function."
391 )]
392 #[document_parameters(
394 "The binary function to apply.",
395 "The first identity.",
396 "The second identity."
397 )]
398 #[document_returns("A new identity containing the result of applying the function.")]
400 #[document_examples]
401 fn lift2<'a, A, B, C>(
415 func: impl Fn(A, B) -> C + 'a,
416 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
417 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
418 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
419 where
420 A: 'a,
421 B: 'a,
422 C: 'a, {
423 fa.lift2(fb, func)
424 }
425 }
426
427 impl Pointed for IdentityBrand {
428 #[document_signature]
432 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
434 #[document_parameters("The value to wrap.")]
436 #[document_returns("An identity containing the value.")]
438 #[document_examples]
440 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
452 Identity(a) }
454 }
455
456 impl ApplyFirst for IdentityBrand {}
457 impl ApplySecond for IdentityBrand {}
458
459 impl Semiapplicative for IdentityBrand {
460 #[document_signature]
464 #[document_type_parameters(
466 "The lifetime of the values.",
467 "The brand of the cloneable function wrapper.",
468 "The type of the input value.",
469 "The type of the output value."
470 )]
471 #[document_parameters(
473 "The identity containing the function.",
474 "The identity containing the value."
475 )]
476 #[document_returns("A new identity containing the result of applying the function.")]
478 #[document_examples]
479 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
493 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
494 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
495 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
496 fa.apply(ff.map(|f| move |a| f(a)))
497 }
498 }
499
500 impl Semimonad for IdentityBrand {
501 #[document_signature]
505 #[document_type_parameters(
507 "The lifetime of the values.",
508 "The type of the result of the first computation.",
509 "The type of the result of the second computation."
510 )]
511 #[document_parameters(
513 "The first identity.",
514 "The function to apply to the value inside the identity."
515 )]
516 #[document_returns("The result of applying `f` to the value.")]
518 #[document_examples]
519 fn bind<'a, A: 'a, B: 'a>(
532 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
533 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
534 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
535 ma.bind(func)
536 }
537 }
538
539 impl Foldable for IdentityBrand {
540 #[document_signature]
544 #[document_type_parameters(
546 "The lifetime of the values.",
547 "The brand of the cloneable function to use.",
548 "The type of the elements in the structure.",
549 "The type of the accumulator."
550 )]
551 #[document_parameters(
553 "The function to apply to each element and the accumulator.",
554 "The initial value of the accumulator.",
555 "The identity to fold."
556 )]
557 #[document_returns("The final accumulator value.")]
559 #[document_examples]
560 fn fold_right<'a, FnBrand, A: 'a, B: 'a>(
573 func: impl Fn(A, B) -> B + 'a,
574 initial: B,
575 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
576 ) -> B
577 where
578 FnBrand: CloneableFn + 'a, {
579 fa.fold_right(func, initial)
580 }
581
582 #[document_signature]
586 #[document_type_parameters(
588 "The lifetime of the values.",
589 "The brand of the cloneable function to use.",
590 "The type of the elements in the structure.",
591 "The type of the accumulator."
592 )]
593 #[document_parameters(
595 "The function to apply to the accumulator and each element.",
596 "The initial value of the accumulator.",
597 "The structure to fold."
598 )]
599 #[document_returns("The final accumulator value.")]
601 #[document_examples]
602 fn fold_left<'a, FnBrand, A: 'a, B: 'a>(
615 func: impl Fn(B, A) -> B + 'a,
616 initial: B,
617 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
618 ) -> B
619 where
620 FnBrand: CloneableFn + 'a, {
621 fa.fold_left(func, initial)
622 }
623
624 #[document_signature]
628 #[document_type_parameters(
630 "The lifetime of the values.",
631 "The brand of the cloneable function to use.",
632 "The type of the elements in the structure.",
633 "The type of the monoid."
634 )]
635 #[document_parameters("The mapping function.", "The identity to fold.")]
637 #[document_returns("The monoid value.")]
639 #[document_examples]
641 fn fold_map<'a, FnBrand, A: 'a, M>(
654 func: impl Fn(A) -> M + 'a,
655 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
656 ) -> M
657 where
658 M: Monoid + 'a,
659 FnBrand: CloneableFn + 'a, {
660 fa.fold_map(func)
661 }
662 }
663
664 impl Traversable for IdentityBrand {
665 #[document_signature]
669 #[document_type_parameters(
671 "The lifetime of the values.",
672 "The type of the elements in the traversable structure.",
673 "The type of the elements in the resulting traversable structure.",
674 "The applicative context."
675 )]
676 #[document_parameters(
678 "The function to apply to each element, returning a value in an applicative context.",
679 "The identity to traverse."
680 )]
681 #[document_returns("The identity wrapped in the applicative context.")]
683 #[document_examples]
684 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
697 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
698 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
699 ) -> 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>)>)
700 where
701 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
702 ta.traverse::<B, F>(func)
703 }
704
705 #[document_signature]
709 #[document_type_parameters(
711 "The lifetime of the values.",
712 "The type of the elements in the traversable structure.",
713 "The applicative context."
714 )]
715 #[document_parameters("The identity containing the applicative value.")]
717 #[document_returns("The result of the traversal.")]
719 #[document_examples]
724 fn sequence<'a, A: 'a + Clone, F: Applicative>(
737 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>)>)
738 ) -> 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>)>)
739 where
740 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
741 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
742 ta.traverse::<A, F>(|a| a)
743 }
744 }
745
746 impl ParFoldable for IdentityBrand {
747 #[document_signature]
751 #[document_type_parameters(
753 "The lifetime of the values.",
754 "The brand of the cloneable function wrapper.",
755 "The element type.",
756 "The monoid type."
757 )]
758 #[document_parameters("The mapping function.", "The identity to fold.")]
760 #[document_returns("The combined monoid value.")]
762 #[document_examples]
764 fn par_fold_map<'a, FnBrand, A, M>(
778 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
779 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
780 ) -> M
781 where
782 FnBrand: 'a + SendCloneableFn,
783 A: 'a + Clone + Send + Sync,
784 M: Monoid + Send + Sync + 'a, {
785 func(fa.0)
786 }
787
788 #[document_signature]
792 #[document_type_parameters(
794 "The lifetime of the values.",
795 "The brand of the cloneable function wrapper.",
796 "The element type.",
797 "The accumulator type."
798 )]
799 #[document_parameters(
801 "The thread-safe function to apply to each element and the accumulator.",
802 "The initial value of the accumulator.",
803 "The identity to fold."
804 )]
805 #[document_returns("The final accumulator value.")]
807 #[document_examples]
808 fn par_fold_right<'a, FnBrand, A, B>(
822 func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
823 initial: B,
824 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
825 ) -> B
826 where
827 FnBrand: 'a + SendCloneableFn,
828 A: 'a + Clone + Send + Sync,
829 B: Send + Sync + 'a, {
830 func((fa.0, initial))
831 }
832 }
833}
834pub use inner::*;
835
836#[cfg(test)]
837mod tests {
838 use {
839 super::inner::Identity,
840 crate::{
841 brands::{
842 IdentityBrand,
843 OptionBrand,
844 RcFnBrand,
845 },
846 classes::{
847 cloneable_fn::CloneableFn,
848 functor::map,
849 pointed::pure,
850 semiapplicative::apply,
851 semimonad::bind,
852 },
853 functions::{
854 compose,
855 identity,
856 },
857 },
858 quickcheck_macros::quickcheck,
859 };
860
861 #[quickcheck]
865 fn functor_identity(x: i32) -> bool {
866 let x = Identity(x);
867 map::<IdentityBrand, _, _>(identity, x) == x
868 }
869
870 #[quickcheck]
872 fn functor_composition(x: i32) -> bool {
873 let x = Identity(x);
874 let f = |x: i32| x.wrapping_add(1);
875 let g = |x: i32| x.wrapping_mul(2);
876 map::<IdentityBrand, _, _>(compose(f, g), x)
877 == map::<IdentityBrand, _, _>(f, map::<IdentityBrand, _, _>(g, x))
878 }
879
880 #[quickcheck]
884 fn applicative_identity(v: i32) -> bool {
885 let v = Identity(v);
886 apply::<RcFnBrand, IdentityBrand, _, _>(
887 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
888 v,
889 ) == v
890 }
891
892 #[quickcheck]
894 fn applicative_homomorphism(x: i32) -> bool {
895 let f = |x: i32| x.wrapping_mul(2);
896 apply::<RcFnBrand, IdentityBrand, _, _>(
897 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
898 pure::<IdentityBrand, _>(x),
899 ) == pure::<IdentityBrand, _>(f(x))
900 }
901
902 #[quickcheck]
904 fn applicative_composition(
905 w: i32,
906 u_val: i32,
907 v_val: i32,
908 ) -> bool {
909 let w = Identity(w);
910 let v_fn = move |x: i32| x.wrapping_mul(v_val);
911 let u_fn = move |x: i32| x.wrapping_add(u_val);
912
913 let v = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
914 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
915
916 let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w);
918 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
919
920 let composed = move |x| u_fn(v_fn(x));
923 let uv = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(composed));
924
925 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
926
927 lhs == rhs
928 }
929
930 #[quickcheck]
932 fn applicative_interchange(y: i32) -> bool {
933 let f = |x: i32| x.wrapping_mul(2);
935 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f));
936
937 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
938
939 let rhs_fn =
940 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
941 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
942
943 lhs == rhs
944 }
945
946 #[quickcheck]
950 fn monad_left_identity(a: i32) -> bool {
951 let f = |x: i32| Identity(x.wrapping_mul(2));
952 bind::<IdentityBrand, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
953 }
954
955 #[quickcheck]
957 fn monad_right_identity(m: i32) -> bool {
958 let m = Identity(m);
959 bind::<IdentityBrand, _, _>(m, pure::<IdentityBrand, _>) == m
960 }
961
962 #[quickcheck]
964 fn monad_associativity(m: i32) -> bool {
965 let m = Identity(m);
966 let f = |x: i32| Identity(x.wrapping_mul(2));
967 let g = |x: i32| Identity(x.wrapping_add(1));
968 bind::<IdentityBrand, _, _>(bind::<IdentityBrand, _, _>(m, f), g)
969 == bind::<IdentityBrand, _, _>(m, |x| bind::<IdentityBrand, _, _>(f(x), g))
970 }
971
972 #[test]
976 fn map_test() {
977 assert_eq!(map::<IdentityBrand, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
978 }
979
980 #[test]
982 fn bind_test() {
983 assert_eq!(bind::<IdentityBrand, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
984 }
985
986 #[test]
988 fn fold_right_test() {
989 assert_eq!(
990 crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _>(
991 |x: i32, acc| x + acc,
992 0,
993 Identity(1)
994 ),
995 1
996 );
997 }
998
999 #[test]
1001 fn fold_left_test() {
1002 assert_eq!(
1003 crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _>(
1004 |acc, x: i32| acc + x,
1005 0,
1006 Identity(1)
1007 ),
1008 1
1009 );
1010 }
1011
1012 #[test]
1014 fn traverse_test() {
1015 assert_eq!(
1016 crate::classes::traversable::traverse::<IdentityBrand, _, _, OptionBrand>(
1017 |x: i32| Some(x + 1),
1018 Identity(1)
1019 ),
1020 Some(Identity(2))
1021 );
1022 }
1023
1024 #[test]
1028 fn par_fold_map_test() {
1029 use crate::{
1030 brands::*,
1031 functions::*,
1032 };
1033
1034 let x = Identity(1);
1035 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1036 assert_eq!(par_fold_map::<ArcFnBrand, IdentityBrand, _, _>(f, x), "1".to_string());
1037 }
1038
1039 #[test]
1041 fn par_fold_right_test() {
1042 use crate::{
1043 brands::*,
1044 functions::*,
1045 };
1046
1047 let x = Identity(1);
1048 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1049 assert_eq!(par_fold_right::<ArcFnBrand, IdentityBrand, _, _>(f, 10, x), 11);
1050 }
1051}