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 Pointed,
21 Semiapplicative,
22 Semimonad,
23 Traversable,
24 },
25 impl_kind,
26 kinds::*,
27 },
28 fp_macros::*,
29 };
30
31 #[document_type_parameters("The type of the wrapped value.")]
45 #[document_fields("The wrapped value.")]
47 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
50 pub struct Identity<A>(pub A);
51
52 impl_kind! {
53 for IdentityBrand {
54 type Of<'a, A: 'a>: 'a = Identity<A>;
55 }
56 }
57
58 #[document_type_parameters("The type of the wrapped value.")]
59 #[document_parameters("The identity instance.")]
60 impl<A> Identity<A> {
61 #[document_signature]
66 #[document_type_parameters("The type of the result of applying the function.")]
68 #[document_parameters("The function to apply.")]
70 #[document_returns("A new identity containing the result of applying the function.")]
72 #[document_examples]
74 pub fn map<B>(
83 self,
84 f: impl FnOnce(A) -> B,
85 ) -> Identity<B> {
86 Identity(f(self.0))
87 }
88
89 #[document_signature]
93 #[document_type_parameters(
95 "The type of the other identity's value.",
96 "The return type of the function."
97 )]
98 #[document_parameters("The other identity.", "The binary function to apply.")]
100 #[document_returns("A new identity containing the result of applying the function.")]
102 #[document_examples]
104 pub fn lift2<B, C>(
114 self,
115 other: Identity<B>,
116 f: impl FnOnce(A, B) -> C,
117 ) -> Identity<C> {
118 Identity(f(self.0, other.0))
119 }
120
121 #[document_signature]
125 #[document_type_parameters("The return type of the wrapped function.")]
127 #[document_parameters("The identity containing the function.")]
129 #[document_returns("A new identity containing the result.")]
131 #[document_examples]
133 pub fn apply<B>(
143 self,
144 ff: Identity<impl FnOnce(A) -> B>,
145 ) -> Identity<B> {
146 Identity(ff.0(self.0))
147 }
148
149 #[document_signature]
154 #[document_type_parameters("The type of the result of the chained computation.")]
156 #[document_parameters("The function to apply to the value inside the identity.")]
158 #[document_returns("The result of applying `f` to the value.")]
160 #[document_examples]
162 pub fn bind<B>(
171 self,
172 f: impl FnOnce(A) -> Identity<B>,
173 ) -> Identity<B> {
174 f(self.0)
175 }
176
177 #[document_signature]
181 #[document_type_parameters("The type of the accumulator.")]
183 #[document_parameters(
185 "The function to apply to the element and the accumulator.",
186 "The initial value of the accumulator."
187 )]
188 #[document_returns("The final accumulator value.")]
190 #[document_examples]
192 pub fn fold_right<B>(
201 self,
202 f: impl FnOnce(A, B) -> B,
203 initial: B,
204 ) -> B {
205 f(self.0, initial)
206 }
207
208 #[document_signature]
212 #[document_type_parameters("The type of the accumulator.")]
214 #[document_parameters(
216 "The function to apply to the accumulator and the element.",
217 "The initial value of the accumulator."
218 )]
219 #[document_returns("The final accumulator value.")]
221 #[document_examples]
223 pub fn fold_left<B>(
232 self,
233 f: impl FnOnce(B, A) -> B,
234 initial: B,
235 ) -> B {
236 f(initial, self.0)
237 }
238
239 #[document_signature]
243 #[document_type_parameters("The monoid type.")]
245 #[document_parameters("The mapping function.")]
247 #[document_returns("The monoid value.")]
249 #[document_examples]
251 pub fn fold_map<M>(
260 self,
261 f: impl FnOnce(A) -> M,
262 ) -> M {
263 f(self.0)
264 }
265 }
266
267 #[document_type_parameters("The lifetime of the values.", "The type of the wrapped value.")]
268 #[document_parameters("The identity instance.")]
269 impl<'a, A: 'a> Identity<A> {
270 #[document_signature]
274 #[document_type_parameters(
276 "The type of the elements in the resulting identity.",
277 "The applicative context."
278 )]
279 #[document_parameters(
281 "The function to apply, returning a value in an applicative context."
282 )]
283 #[document_returns("The identity wrapped in the applicative context.")]
285 #[document_examples]
287 pub fn traverse<B: 'a + Clone, F: Applicative>(
299 self,
300 f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
301 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<B>>)
302 where
303 Identity<B>: Clone, {
304 F::map(|b| Identity(b), f(self.0))
305 }
306
307 #[document_signature]
311 #[document_type_parameters(
313 "The inner type wrapped in the applicative context.",
314 "The applicative context."
315 )]
316 #[document_returns("The identity wrapped in the applicative context.")]
318 #[document_examples]
320 pub fn sequence<InnerA: 'a + Clone, F: Applicative>(
332 self
333 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<InnerA>>)
334 where
335 A: Into<Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, InnerA>)>,
336 Identity<InnerA>: Clone, {
337 F::map(|a| Identity(a), self.0.into())
338 }
339 }
340
341 impl Functor for IdentityBrand {
342 #[document_signature]
346 #[document_type_parameters(
348 "The lifetime of the value.",
349 "The type of the value inside the identity.",
350 "The type of the result of applying the function."
351 )]
352 #[document_parameters("The function to apply.", "The identity to map over.")]
354 #[document_returns("A new identity containing the result of applying the function.")]
356 #[document_examples]
358 fn map<'a, A: 'a, B: 'a>(
371 func: impl Fn(A) -> B + 'a,
372 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
373 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
374 fa.map(func)
375 }
376 }
377
378 impl Lift for IdentityBrand {
379 #[document_signature]
383 #[document_type_parameters(
385 "The lifetime of the values.",
386 "The type of the first identity's value.",
387 "The type of the second identity's value.",
388 "The return type of the function."
389 )]
390 #[document_parameters(
392 "The binary function to apply.",
393 "The first identity.",
394 "The second identity."
395 )]
396 #[document_returns("A new identity containing the result of applying the function.")]
398 #[document_examples]
399 fn lift2<'a, A, B, C>(
413 func: impl Fn(A, B) -> C + 'a,
414 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
415 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
416 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
417 where
418 A: 'a,
419 B: 'a,
420 C: 'a, {
421 fa.lift2(fb, func)
422 }
423 }
424
425 impl Pointed for IdentityBrand {
426 #[document_signature]
430 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
432 #[document_parameters("The value to wrap.")]
434 #[document_returns("An identity containing the value.")]
436 #[document_examples]
438 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
450 Identity(a) }
452 }
453
454 impl ApplyFirst for IdentityBrand {}
455 impl ApplySecond for IdentityBrand {}
456
457 impl Semiapplicative for IdentityBrand {
458 #[document_signature]
462 #[document_type_parameters(
464 "The lifetime of the values.",
465 "The brand of the cloneable function wrapper.",
466 "The type of the input value.",
467 "The type of the output value."
468 )]
469 #[document_parameters(
471 "The identity containing the function.",
472 "The identity containing the value."
473 )]
474 #[document_returns("A new identity containing the result of applying the function.")]
476 #[document_examples]
477 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
491 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
492 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
493 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
494 fa.apply(ff.map(|f| move |a| f(a)))
495 }
496 }
497
498 impl Semimonad for IdentityBrand {
499 #[document_signature]
503 #[document_type_parameters(
505 "The lifetime of the values.",
506 "The type of the result of the first computation.",
507 "The type of the result of the second computation."
508 )]
509 #[document_parameters(
511 "The first identity.",
512 "The function to apply to the value inside the identity."
513 )]
514 #[document_returns("The result of applying `f` to the value.")]
516 #[document_examples]
517 fn bind<'a, A: 'a, B: 'a>(
530 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
531 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
532 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
533 ma.bind(func)
534 }
535 }
536
537 impl Foldable for IdentityBrand {
538 #[document_signature]
542 #[document_type_parameters(
544 "The lifetime of the values.",
545 "The brand of the cloneable function to use.",
546 "The type of the elements in the structure.",
547 "The type of the accumulator."
548 )]
549 #[document_parameters(
551 "The function to apply to each element and the accumulator.",
552 "The initial value of the accumulator.",
553 "The identity to fold."
554 )]
555 #[document_returns("The final accumulator value.")]
557 #[document_examples]
558 fn fold_right<'a, FnBrand, A: 'a, B: 'a>(
571 func: impl Fn(A, B) -> B + 'a,
572 initial: B,
573 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
574 ) -> B
575 where
576 FnBrand: CloneableFn + 'a, {
577 fa.fold_right(func, initial)
578 }
579
580 #[document_signature]
584 #[document_type_parameters(
586 "The lifetime of the values.",
587 "The brand of the cloneable function to use.",
588 "The type of the elements in the structure.",
589 "The type of the accumulator."
590 )]
591 #[document_parameters(
593 "The function to apply to the accumulator and each element.",
594 "The initial value of the accumulator.",
595 "The structure to fold."
596 )]
597 #[document_returns("The final accumulator value.")]
599 #[document_examples]
600 fn fold_left<'a, FnBrand, A: 'a, B: 'a>(
613 func: impl Fn(B, A) -> B + 'a,
614 initial: B,
615 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
616 ) -> B
617 where
618 FnBrand: CloneableFn + 'a, {
619 fa.fold_left(func, initial)
620 }
621
622 #[document_signature]
626 #[document_type_parameters(
628 "The lifetime of the values.",
629 "The brand of the cloneable function to use.",
630 "The type of the elements in the structure.",
631 "The type of the monoid."
632 )]
633 #[document_parameters("The mapping function.", "The identity to fold.")]
635 #[document_returns("The monoid value.")]
637 #[document_examples]
639 fn fold_map<'a, FnBrand, A: 'a, M>(
652 func: impl Fn(A) -> M + 'a,
653 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
654 ) -> M
655 where
656 M: Monoid + 'a,
657 FnBrand: CloneableFn + 'a, {
658 fa.fold_map(func)
659 }
660 }
661
662 impl Traversable for IdentityBrand {
663 #[document_signature]
667 #[document_type_parameters(
669 "The lifetime of the values.",
670 "The type of the elements in the traversable structure.",
671 "The type of the elements in the resulting traversable structure.",
672 "The applicative context."
673 )]
674 #[document_parameters(
676 "The function to apply to each element, returning a value in an applicative context.",
677 "The identity to traverse."
678 )]
679 #[document_returns("The identity wrapped in the applicative context.")]
681 #[document_examples]
682 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
695 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
696 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
697 ) -> 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>)>)
698 where
699 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
700 ta.traverse::<B, F>(func)
701 }
702
703 #[document_signature]
707 #[document_type_parameters(
709 "The lifetime of the values.",
710 "The type of the elements in the traversable structure.",
711 "The applicative context."
712 )]
713 #[document_parameters("The identity containing the applicative value.")]
715 #[document_returns("The result of the traversal.")]
717 #[document_examples]
722 fn sequence<'a, A: 'a + Clone, F: Applicative>(
735 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>)>)
736 ) -> 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>)>)
737 where
738 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
739 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
740 ta.traverse::<A, F>(|a| a)
741 }
742 }
743}
744pub use inner::*;
745
746#[cfg(test)]
747mod tests {
748 use {
749 super::inner::Identity,
750 crate::{
751 brands::{
752 IdentityBrand,
753 OptionBrand,
754 RcFnBrand,
755 },
756 classes::{
757 cloneable_fn::CloneableFn,
758 functor::map,
759 pointed::pure,
760 semiapplicative::apply,
761 semimonad::bind,
762 },
763 functions::{
764 compose,
765 identity,
766 },
767 },
768 quickcheck_macros::quickcheck,
769 };
770
771 #[quickcheck]
775 fn functor_identity(x: i32) -> bool {
776 let x = Identity(x);
777 map::<IdentityBrand, _, _>(identity, x) == x
778 }
779
780 #[quickcheck]
782 fn functor_composition(x: i32) -> bool {
783 let x = Identity(x);
784 let f = |x: i32| x.wrapping_add(1);
785 let g = |x: i32| x.wrapping_mul(2);
786 map::<IdentityBrand, _, _>(compose(f, g), x)
787 == map::<IdentityBrand, _, _>(f, map::<IdentityBrand, _, _>(g, x))
788 }
789
790 #[quickcheck]
794 fn applicative_identity(v: i32) -> bool {
795 let v = Identity(v);
796 apply::<RcFnBrand, IdentityBrand, _, _>(
797 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
798 v,
799 ) == v
800 }
801
802 #[quickcheck]
804 fn applicative_homomorphism(x: i32) -> bool {
805 let f = |x: i32| x.wrapping_mul(2);
806 apply::<RcFnBrand, IdentityBrand, _, _>(
807 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
808 pure::<IdentityBrand, _>(x),
809 ) == pure::<IdentityBrand, _>(f(x))
810 }
811
812 #[quickcheck]
814 fn applicative_composition(
815 w: i32,
816 u_val: i32,
817 v_val: i32,
818 ) -> bool {
819 let w = Identity(w);
820 let v_fn = move |x: i32| x.wrapping_mul(v_val);
821 let u_fn = move |x: i32| x.wrapping_add(u_val);
822
823 let v = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
824 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
825
826 let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w);
828 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
829
830 let composed = move |x| u_fn(v_fn(x));
833 let uv = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(composed));
834
835 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
836
837 lhs == rhs
838 }
839
840 #[quickcheck]
842 fn applicative_interchange(y: i32) -> bool {
843 let f = |x: i32| x.wrapping_mul(2);
845 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f));
846
847 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
848
849 let rhs_fn =
850 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
851 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
852
853 lhs == rhs
854 }
855
856 #[quickcheck]
860 fn monad_left_identity(a: i32) -> bool {
861 let f = |x: i32| Identity(x.wrapping_mul(2));
862 bind::<IdentityBrand, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
863 }
864
865 #[quickcheck]
867 fn monad_right_identity(m: i32) -> bool {
868 let m = Identity(m);
869 bind::<IdentityBrand, _, _>(m, pure::<IdentityBrand, _>) == m
870 }
871
872 #[quickcheck]
874 fn monad_associativity(m: i32) -> bool {
875 let m = Identity(m);
876 let f = |x: i32| Identity(x.wrapping_mul(2));
877 let g = |x: i32| Identity(x.wrapping_add(1));
878 bind::<IdentityBrand, _, _>(bind::<IdentityBrand, _, _>(m, f), g)
879 == bind::<IdentityBrand, _, _>(m, |x| bind::<IdentityBrand, _, _>(f(x), g))
880 }
881
882 #[test]
886 fn map_test() {
887 assert_eq!(map::<IdentityBrand, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
888 }
889
890 #[test]
892 fn bind_test() {
893 assert_eq!(bind::<IdentityBrand, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
894 }
895
896 #[test]
898 fn fold_right_test() {
899 assert_eq!(
900 crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _>(
901 |x: i32, acc| x + acc,
902 0,
903 Identity(1)
904 ),
905 1
906 );
907 }
908
909 #[test]
911 fn fold_left_test() {
912 assert_eq!(
913 crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _>(
914 |acc, x: i32| acc + x,
915 0,
916 Identity(1)
917 ),
918 1
919 );
920 }
921
922 #[test]
924 fn traverse_test() {
925 assert_eq!(
926 crate::classes::traversable::traverse::<IdentityBrand, _, _, OptionBrand>(
927 |x: i32| Some(x + 1),
928 Identity(1)
929 ),
930 Some(Identity(2))
931 );
932 }
933}