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 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
48 pub struct Identity<A>(
49 pub A,
51 );
52
53 impl_kind! {
54 for IdentityBrand {
55 type Of<'a, A: 'a>: 'a = Identity<A>;
56 }
57 }
58
59 #[document_type_parameters("The type of the wrapped value.")]
60 #[document_parameters("The identity instance.")]
61 impl<A> Identity<A> {
62 #[document_signature]
67 #[document_type_parameters("The type of the result of applying the function.")]
69 #[document_parameters("The function to apply.")]
71 #[document_returns("A new identity containing the result of applying the function.")]
73 #[document_examples]
75 pub fn map<B>(
84 self,
85 f: impl FnOnce(A) -> B,
86 ) -> Identity<B> {
87 Identity(f(self.0))
88 }
89
90 #[document_signature]
94 #[document_type_parameters(
96 "The type of the other identity's value.",
97 "The return type of the function."
98 )]
99 #[document_parameters("The other identity.", "The binary function to apply.")]
101 #[document_returns("A new identity containing the result of applying the function.")]
103 #[document_examples]
105 pub fn lift2<B, C>(
115 self,
116 other: Identity<B>,
117 f: impl FnOnce(A, B) -> C,
118 ) -> Identity<C> {
119 Identity(f(self.0, other.0))
120 }
121
122 #[document_signature]
126 #[document_type_parameters("The return type of the wrapped function.")]
128 #[document_parameters("The identity containing the function.")]
130 #[document_returns("A new identity containing the result.")]
132 #[document_examples]
134 pub fn apply<B>(
144 self,
145 ff: Identity<impl FnOnce(A) -> B>,
146 ) -> Identity<B> {
147 Identity(ff.0(self.0))
148 }
149
150 #[document_signature]
155 #[document_type_parameters("The type of the result of the chained computation.")]
157 #[document_parameters("The function to apply to the value inside the identity.")]
159 #[document_returns("The result of applying `f` to the value.")]
161 #[document_examples]
163 pub fn bind<B>(
172 self,
173 f: impl FnOnce(A) -> Identity<B>,
174 ) -> Identity<B> {
175 f(self.0)
176 }
177
178 #[document_signature]
182 #[document_type_parameters("The type of the accumulator.")]
184 #[document_parameters(
186 "The function to apply to the element and the accumulator.",
187 "The initial value of the accumulator."
188 )]
189 #[document_returns("The final accumulator value.")]
191 #[document_examples]
193 pub fn fold_right<B>(
202 self,
203 f: impl FnOnce(A, B) -> B,
204 initial: B,
205 ) -> B {
206 f(self.0, initial)
207 }
208
209 #[document_signature]
213 #[document_type_parameters("The type of the accumulator.")]
215 #[document_parameters(
217 "The function to apply to the accumulator and the element.",
218 "The initial value of the accumulator."
219 )]
220 #[document_returns("The final accumulator value.")]
222 #[document_examples]
224 pub fn fold_left<B>(
233 self,
234 f: impl FnOnce(B, A) -> B,
235 initial: B,
236 ) -> B {
237 f(initial, self.0)
238 }
239
240 #[document_signature]
244 #[document_type_parameters("The monoid type.")]
246 #[document_parameters("The mapping function.")]
248 #[document_returns("The monoid value.")]
250 #[document_examples]
252 pub fn fold_map<M>(
261 self,
262 f: impl FnOnce(A) -> M,
263 ) -> M {
264 f(self.0)
265 }
266 }
267
268 #[document_type_parameters("The lifetime of the values.", "The type of the wrapped value.")]
269 #[document_parameters("The identity instance.")]
270 impl<'a, A: 'a> Identity<A> {
271 #[document_signature]
275 #[document_type_parameters(
277 "The type of the elements in the resulting identity.",
278 "The applicative context."
279 )]
280 #[document_parameters(
282 "The function to apply, returning a value in an applicative context."
283 )]
284 #[document_returns("The identity wrapped in the applicative context.")]
286 #[document_examples]
288 pub fn traverse<B: 'a + Clone, F: Applicative>(
300 self,
301 f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
302 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<B>>)
303 where
304 Identity<B>: Clone, {
305 F::map(|b| Identity(b), f(self.0))
306 }
307
308 #[document_signature]
312 #[document_type_parameters(
314 "The inner type wrapped in the applicative context.",
315 "The applicative context."
316 )]
317 #[document_returns("The identity wrapped in the applicative context.")]
319 #[document_examples]
321 pub fn sequence<InnerA: 'a + Clone, F: Applicative>(
333 self
334 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<InnerA>>)
335 where
336 A: Into<Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, InnerA>)>,
337 Identity<InnerA>: Clone, {
338 F::map(|a| Identity(a), self.0.into())
339 }
340 }
341
342 impl Functor for IdentityBrand {
343 #[document_signature]
347 #[document_type_parameters(
349 "The lifetime of the value.",
350 "The type of the value inside the identity.",
351 "The type of the result of applying the function."
352 )]
353 #[document_parameters("The function to apply.", "The identity to map over.")]
355 #[document_returns("A new identity containing the result of applying the function.")]
357 #[document_examples]
359 fn map<'a, A: 'a, B: 'a>(
372 func: impl Fn(A) -> B + 'a,
373 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
374 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
375 fa.map(func)
376 }
377 }
378
379 impl Lift for IdentityBrand {
380 #[document_signature]
384 #[document_type_parameters(
386 "The lifetime of the values.",
387 "The type of the first identity's value.",
388 "The type of the second identity's value.",
389 "The return type of the function."
390 )]
391 #[document_parameters(
393 "The binary function to apply.",
394 "The first identity.",
395 "The second identity."
396 )]
397 #[document_returns("A new identity containing the result of applying the function.")]
399 #[document_examples]
400 fn lift2<'a, A, B, C>(
414 func: impl Fn(A, B) -> C + 'a,
415 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
416 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
417 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
418 where
419 A: 'a,
420 B: 'a,
421 C: 'a, {
422 fa.lift2(fb, func)
423 }
424 }
425
426 impl Pointed for IdentityBrand {
427 #[document_signature]
431 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
433 #[document_parameters("The value to wrap.")]
435 #[document_returns("An identity containing the value.")]
437 #[document_examples]
439 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
451 Identity(a) }
453 }
454
455 impl ApplyFirst for IdentityBrand {}
456 impl ApplySecond for IdentityBrand {}
457
458 impl Semiapplicative for IdentityBrand {
459 #[document_signature]
463 #[document_type_parameters(
465 "The lifetime of the values.",
466 "The brand of the cloneable function wrapper.",
467 "The type of the input value.",
468 "The type of the output value."
469 )]
470 #[document_parameters(
472 "The identity containing the function.",
473 "The identity containing the value."
474 )]
475 #[document_returns("A new identity containing the result of applying the function.")]
477 #[document_examples]
478 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
492 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
493 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
494 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
495 fa.apply(ff.map(|f| move |a| f(a)))
496 }
497 }
498
499 impl Semimonad for IdentityBrand {
500 #[document_signature]
504 #[document_type_parameters(
506 "The lifetime of the values.",
507 "The type of the result of the first computation.",
508 "The type of the result of the second computation."
509 )]
510 #[document_parameters(
512 "The first identity.",
513 "The function to apply to the value inside the identity."
514 )]
515 #[document_returns("The result of applying `f` to the value.")]
517 #[document_examples]
518 fn bind<'a, A: 'a, B: 'a>(
531 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
532 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
533 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
534 ma.bind(func)
535 }
536 }
537
538 impl Foldable for IdentityBrand {
539 #[document_signature]
543 #[document_type_parameters(
545 "The lifetime of the values.",
546 "The brand of the cloneable function to use.",
547 "The type of the elements in the structure.",
548 "The type of the accumulator."
549 )]
550 #[document_parameters(
552 "The function to apply to each element and the accumulator.",
553 "The initial value of the accumulator.",
554 "The identity to fold."
555 )]
556 #[document_returns("The final accumulator value.")]
558 #[document_examples]
559 fn fold_right<'a, FnBrand, A: 'a, B: 'a>(
572 func: impl Fn(A, B) -> B + 'a,
573 initial: B,
574 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
575 ) -> B
576 where
577 FnBrand: CloneableFn + 'a, {
578 fa.fold_right(func, initial)
579 }
580
581 #[document_signature]
585 #[document_type_parameters(
587 "The lifetime of the values.",
588 "The brand of the cloneable function to use.",
589 "The type of the elements in the structure.",
590 "The type of the accumulator."
591 )]
592 #[document_parameters(
594 "The function to apply to the accumulator and each element.",
595 "The initial value of the accumulator.",
596 "The structure to fold."
597 )]
598 #[document_returns("The final accumulator value.")]
600 #[document_examples]
601 fn fold_left<'a, FnBrand, A: 'a, B: 'a>(
614 func: impl Fn(B, A) -> B + 'a,
615 initial: B,
616 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
617 ) -> B
618 where
619 FnBrand: CloneableFn + 'a, {
620 fa.fold_left(func, initial)
621 }
622
623 #[document_signature]
627 #[document_type_parameters(
629 "The lifetime of the values.",
630 "The brand of the cloneable function to use.",
631 "The type of the elements in the structure.",
632 "The type of the monoid."
633 )]
634 #[document_parameters("The mapping function.", "The identity to fold.")]
636 #[document_returns("The monoid value.")]
638 #[document_examples]
640 fn fold_map<'a, FnBrand, A: 'a, M>(
653 func: impl Fn(A) -> M + 'a,
654 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
655 ) -> M
656 where
657 M: Monoid + 'a,
658 FnBrand: CloneableFn + 'a, {
659 fa.fold_map(func)
660 }
661 }
662
663 impl Traversable for IdentityBrand {
664 #[document_signature]
668 #[document_type_parameters(
670 "The lifetime of the values.",
671 "The type of the elements in the traversable structure.",
672 "The type of the elements in the resulting traversable structure.",
673 "The applicative context."
674 )]
675 #[document_parameters(
677 "The function to apply to each element, returning a value in an applicative context.",
678 "The identity to traverse."
679 )]
680 #[document_returns("The identity wrapped in the applicative context.")]
682 #[document_examples]
683 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
696 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
697 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
698 ) -> 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>)>)
699 where
700 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
701 ta.traverse::<B, F>(func)
702 }
703
704 #[document_signature]
708 #[document_type_parameters(
710 "The lifetime of the values.",
711 "The type of the elements in the traversable structure.",
712 "The applicative context."
713 )]
714 #[document_parameters("The identity containing the applicative value.")]
716 #[document_returns("The result of the traversal.")]
718 #[document_examples]
723 fn sequence<'a, A: 'a + Clone, F: Applicative>(
736 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>)>)
737 ) -> 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>)>)
738 where
739 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
740 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
741 ta.traverse::<A, F>(|a| a)
742 }
743 }
744}
745pub use inner::*;
746
747#[cfg(test)]
748mod tests {
749 use {
750 super::inner::Identity,
751 crate::{
752 brands::{
753 IdentityBrand,
754 OptionBrand,
755 RcFnBrand,
756 },
757 classes::{
758 cloneable_fn::CloneableFn,
759 functor::map,
760 pointed::pure,
761 semiapplicative::apply,
762 semimonad::bind,
763 },
764 functions::{
765 compose,
766 identity,
767 },
768 },
769 quickcheck_macros::quickcheck,
770 };
771
772 #[quickcheck]
776 fn functor_identity(x: i32) -> bool {
777 let x = Identity(x);
778 map::<IdentityBrand, _, _>(identity, x) == x
779 }
780
781 #[quickcheck]
783 fn functor_composition(x: i32) -> bool {
784 let x = Identity(x);
785 let f = |x: i32| x.wrapping_add(1);
786 let g = |x: i32| x.wrapping_mul(2);
787 map::<IdentityBrand, _, _>(compose(f, g), x)
788 == map::<IdentityBrand, _, _>(f, map::<IdentityBrand, _, _>(g, x))
789 }
790
791 #[quickcheck]
795 fn applicative_identity(v: i32) -> bool {
796 let v = Identity(v);
797 apply::<RcFnBrand, IdentityBrand, _, _>(
798 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
799 v,
800 ) == v
801 }
802
803 #[quickcheck]
805 fn applicative_homomorphism(x: i32) -> bool {
806 let f = |x: i32| x.wrapping_mul(2);
807 apply::<RcFnBrand, IdentityBrand, _, _>(
808 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
809 pure::<IdentityBrand, _>(x),
810 ) == pure::<IdentityBrand, _>(f(x))
811 }
812
813 #[quickcheck]
815 fn applicative_composition(
816 w: i32,
817 u_val: i32,
818 v_val: i32,
819 ) -> bool {
820 let w = Identity(w);
821 let v_fn = move |x: i32| x.wrapping_mul(v_val);
822 let u_fn = move |x: i32| x.wrapping_add(u_val);
823
824 let v = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
825 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
826
827 let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w);
829 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
830
831 let composed = move |x| u_fn(v_fn(x));
834 let uv = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(composed));
835
836 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
837
838 lhs == rhs
839 }
840
841 #[quickcheck]
843 fn applicative_interchange(y: i32) -> bool {
844 let f = |x: i32| x.wrapping_mul(2);
846 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f));
847
848 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
849
850 let rhs_fn =
851 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
852 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
853
854 lhs == rhs
855 }
856
857 #[quickcheck]
861 fn monad_left_identity(a: i32) -> bool {
862 let f = |x: i32| Identity(x.wrapping_mul(2));
863 bind::<IdentityBrand, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
864 }
865
866 #[quickcheck]
868 fn monad_right_identity(m: i32) -> bool {
869 let m = Identity(m);
870 bind::<IdentityBrand, _, _>(m, pure::<IdentityBrand, _>) == m
871 }
872
873 #[quickcheck]
875 fn monad_associativity(m: i32) -> bool {
876 let m = Identity(m);
877 let f = |x: i32| Identity(x.wrapping_mul(2));
878 let g = |x: i32| Identity(x.wrapping_add(1));
879 bind::<IdentityBrand, _, _>(bind::<IdentityBrand, _, _>(m, f), g)
880 == bind::<IdentityBrand, _, _>(m, |x| bind::<IdentityBrand, _, _>(f(x), g))
881 }
882
883 #[test]
887 fn map_test() {
888 assert_eq!(map::<IdentityBrand, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
889 }
890
891 #[test]
893 fn bind_test() {
894 assert_eq!(bind::<IdentityBrand, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
895 }
896
897 #[test]
899 fn fold_right_test() {
900 assert_eq!(
901 crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _>(
902 |x: i32, acc| x + acc,
903 0,
904 Identity(1)
905 ),
906 1
907 );
908 }
909
910 #[test]
912 fn fold_left_test() {
913 assert_eq!(
914 crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _>(
915 |acc, x: i32| acc + x,
916 0,
917 Identity(1)
918 ),
919 1
920 );
921 }
922
923 #[test]
925 fn traverse_test() {
926 assert_eq!(
927 crate::classes::traversable::traverse::<IdentityBrand, _, _, OptionBrand>(
928 |x: i32| Some(x + 1),
929 Identity(1)
930 ),
931 Some(Identity(2))
932 );
933 }
934}