1#[fp_macros::document_module]
6mod inner {
7 use crate::{
8 Apply,
9 brands::IdentityBrand,
10 classes::{
11 Applicative, ApplyFirst, ApplySecond, CloneableFn, Foldable, Functor, Lift, Monoid,
12 ParFoldable, Pointed, Semiapplicative, Semimonad, SendCloneableFn, Traversable,
13 },
14 impl_kind,
15 kinds::*,
16 };
17 use fp_macros::{document_fields, document_parameters, document_type_parameters};
18
19 #[document_type_parameters("The type of the wrapped value.")]
36 #[document_fields("The wrapped value.")]
40 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
50 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
51 pub struct Identity<A>(pub A);
52
53 impl_kind! {
54 for IdentityBrand {
55 type Of<'a, A: 'a>: 'a = Identity<A>;
56 }
57 }
58
59 impl Functor for IdentityBrand {
60 #[document_signature]
67 #[document_type_parameters(
71 "The lifetime of the value.",
72 "The type of the value inside the identity.",
73 "The type of the result of applying the function.",
74 "The type of the function to apply."
75 )]
76 #[document_parameters("The function to apply.", "The identity to map over.")]
80 fn map<'a, A: 'a, B: 'a, Func>(
95 func: Func,
96 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
97 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
98 where
99 Func: Fn(A) -> B + 'a,
100 {
101 Identity(func(fa.0))
102 }
103 }
104
105 impl Lift for IdentityBrand {
106 #[document_signature]
113 #[document_type_parameters(
117 "The lifetime of the values.",
118 "The type of the first identity's value.",
119 "The type of the second identity's value.",
120 "The return type of the function.",
121 "The type of the binary function."
122 )]
123 #[document_parameters(
127 "The binary function to apply.",
128 "The first identity.",
129 "The second identity."
130 )]
131 fn lift2<'a, A, B, C, Func>(
147 func: Func,
148 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
149 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
150 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
151 where
152 Func: Fn(A, B) -> C + 'a,
153 A: 'a,
154 B: 'a,
155 C: 'a,
156 {
157 Identity(func(fa.0, fb.0))
158 }
159 }
160
161 impl Pointed for IdentityBrand {
162 #[document_signature]
169 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
173 #[document_parameters("The value to wrap.")]
177 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
191 Identity(a)
192 }
193 }
194
195 impl ApplyFirst for IdentityBrand {}
196 impl ApplySecond for IdentityBrand {}
197
198 impl Semiapplicative for IdentityBrand {
199 #[document_signature]
206 #[document_type_parameters(
210 "The lifetime of the values.",
211 "The brand of the cloneable function wrapper.",
212 "The type of the input value.",
213 "The type of the output value."
214 )]
215 #[document_parameters(
219 "The identity containing the function.",
220 "The identity containing the value."
221 )]
222 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
238 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
239 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
240 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
241 Identity(ff.0(fa.0))
242 }
243 }
244
245 impl Semimonad for IdentityBrand {
246 #[document_signature]
253 #[document_type_parameters(
257 "The lifetime of the values.",
258 "The type of the result of the first computation.",
259 "The type of the result of the second computation.",
260 "The type of the function to apply."
261 )]
262 #[document_parameters(
266 "The first identity.",
267 "The function to apply to the value inside the identity."
268 )]
269 fn bind<'a, A: 'a, B: 'a, Func>(
284 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
285 func: Func,
286 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
287 where
288 Func: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
289 {
290 func(ma.0)
291 }
292 }
293
294 impl Foldable for IdentityBrand {
295 #[document_signature]
302 #[document_type_parameters(
306 "The lifetime of the values.",
307 "The brand of the cloneable function to use.",
308 "The type of the elements in the structure.",
309 "The type of the accumulator.",
310 "The type of the folding function."
311 )]
312 #[document_parameters(
316 "The function to apply to each element and the accumulator.",
317 "The initial value of the accumulator.",
318 "The identity to fold."
319 )]
320 fn fold_right<'a, FnBrand, A: 'a, B: 'a, Func>(
335 func: Func,
336 initial: B,
337 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
338 ) -> B
339 where
340 Func: Fn(A, B) -> B + 'a,
341 FnBrand: CloneableFn + 'a,
342 {
343 func(fa.0, initial)
344 }
345
346 #[document_signature]
353 #[document_type_parameters(
357 "The lifetime of the values.",
358 "The brand of the cloneable function to use.",
359 "The type of the elements in the structure.",
360 "The type of the accumulator.",
361 "The type of the folding function."
362 )]
363 #[document_parameters(
367 "The function to apply to the accumulator and each element.",
368 "The initial value of the accumulator.",
369 "The structure to fold."
370 )]
371 fn fold_left<'a, FnBrand, A: 'a, B: 'a, Func>(
386 func: Func,
387 initial: B,
388 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
389 ) -> B
390 where
391 Func: Fn(B, A) -> B + 'a,
392 FnBrand: CloneableFn + 'a,
393 {
394 func(initial, fa.0)
395 }
396
397 #[document_signature]
404 #[document_type_parameters(
408 "The lifetime of the values.",
409 "The brand of the cloneable function to use.",
410 "The type of the elements in the structure.",
411 "The type of the monoid.",
412 "The type of the mapping function."
413 )]
414 #[document_parameters("The mapping function.", "The identity to fold.")]
418 fn fold_map<'a, FnBrand, A: 'a, M, Func>(
433 func: Func,
434 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
435 ) -> M
436 where
437 M: Monoid + 'a,
438 Func: Fn(A) -> M + 'a,
439 FnBrand: CloneableFn + 'a,
440 {
441 func(fa.0)
442 }
443 }
444
445 impl Traversable for IdentityBrand {
446 #[document_signature]
453 #[document_type_parameters(
457 "The lifetime of the values.",
458 "The type of the elements in the traversable structure.",
459 "The type of the elements in the resulting traversable structure.",
460 "The applicative context.",
461 "The type of the function to apply."
462 )]
463 #[document_parameters(
467 "The function to apply to each element, returning a value in an applicative context.",
468 "The identity to traverse."
469 )]
470 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative, Func>(
485 func: Func,
486 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
487 ) -> 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>)>)
488 where
489 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
490 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
491 {
492 F::map(|b| Identity(b), func(ta.0))
493 }
494 #[document_signature]
501 #[document_type_parameters(
505 "The lifetime of the values.",
506 "The type of the elements in the traversable structure.",
507 "The applicative context."
508 )]
509 #[document_parameters("The identity containing the applicative value.")]
513 fn sequence<'a, A: 'a + Clone, F: Applicative>(
528 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>)>)
529 ) -> 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>)>)
530 where
531 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
532 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
533 {
534 F::map(|a| Identity(a), ta.0)
535 }
536 }
537
538 impl ParFoldable for IdentityBrand {
539 #[document_signature]
546 #[document_type_parameters(
550 "The lifetime of the values.",
551 "The brand of the cloneable function wrapper.",
552 "The element type.",
553 "The monoid type."
554 )]
555 #[document_parameters("The mapping function.", "The identity to fold.")]
559 fn par_fold_map<'a, FnBrand, A, M>(
575 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
576 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
577 ) -> M
578 where
579 FnBrand: 'a + SendCloneableFn,
580 A: 'a + Clone + Send + Sync,
581 M: Monoid + Send + Sync + 'a,
582 {
583 func(fa.0)
584 }
585
586 #[document_signature]
593 #[document_type_parameters(
597 "The lifetime of the values.",
598 "The brand of the cloneable function wrapper.",
599 "The element type.",
600 "The accumulator type."
601 )]
602 #[document_parameters(
606 "The thread-safe function to apply to each element and the accumulator.",
607 "The initial value of the accumulator.",
608 "The identity to fold."
609 )]
610 fn par_fold_right<'a, FnBrand, A, B>(
626 func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
627 initial: B,
628 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
629 ) -> B
630 where
631 FnBrand: 'a + SendCloneableFn,
632 A: 'a + Clone + Send + Sync,
633 B: Send + Sync + 'a,
634 {
635 func((fa.0, initial))
636 }
637 }
638}
639pub use inner::*;
640
641#[cfg(test)]
642mod tests {
643 use super::inner::Identity;
644 use crate::{
645 brands::{IdentityBrand, OptionBrand, RcFnBrand},
646 classes::{
647 cloneable_fn::CloneableFn, functor::map, pointed::pure, semiapplicative::apply,
648 semimonad::bind,
649 },
650 functions::{compose, identity},
651 };
652 use quickcheck_macros::quickcheck;
653
654 #[quickcheck]
658 fn functor_identity(x: i32) -> bool {
659 let x = Identity(x);
660 map::<IdentityBrand, _, _, _>(identity, x) == x
661 }
662
663 #[quickcheck]
665 fn functor_composition(x: i32) -> bool {
666 let x = Identity(x);
667 let f = |x: i32| x.wrapping_add(1);
668 let g = |x: i32| x.wrapping_mul(2);
669 map::<IdentityBrand, _, _, _>(compose(f, g), x)
670 == map::<IdentityBrand, _, _, _>(f, map::<IdentityBrand, _, _, _>(g, x))
671 }
672
673 #[quickcheck]
677 fn applicative_identity(v: i32) -> bool {
678 let v = Identity(v);
679 apply::<RcFnBrand, IdentityBrand, _, _>(
680 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
681 v,
682 ) == v
683 }
684
685 #[quickcheck]
687 fn applicative_homomorphism(x: i32) -> bool {
688 let f = |x: i32| x.wrapping_mul(2);
689 apply::<RcFnBrand, IdentityBrand, _, _>(
690 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
691 pure::<IdentityBrand, _>(x),
692 ) == pure::<IdentityBrand, _>(f(x))
693 }
694
695 #[quickcheck]
697 fn applicative_composition(
698 w: i32,
699 u_val: i32,
700 v_val: i32,
701 ) -> bool {
702 let w = Identity(w);
703 let v_fn = move |x: i32| x.wrapping_mul(v_val);
704 let u_fn = move |x: i32| x.wrapping_add(u_val);
705
706 let v = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
707 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
708
709 let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w.clone());
711 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
712
713 let composed = move |x| u_fn(v_fn(x));
716 let uv = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(composed));
717
718 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
719
720 lhs == rhs
721 }
722
723 #[quickcheck]
725 fn applicative_interchange(y: i32) -> bool {
726 let f = |x: i32| x.wrapping_mul(2);
728 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f));
729
730 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
731
732 let rhs_fn =
733 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
734 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
735
736 lhs == rhs
737 }
738
739 #[quickcheck]
743 fn monad_left_identity(a: i32) -> bool {
744 let f = |x: i32| Identity(x.wrapping_mul(2));
745 bind::<IdentityBrand, _, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
746 }
747
748 #[quickcheck]
750 fn monad_right_identity(m: i32) -> bool {
751 let m = Identity(m);
752 bind::<IdentityBrand, _, _, _>(m, pure::<IdentityBrand, _>) == m
753 }
754
755 #[quickcheck]
757 fn monad_associativity(m: i32) -> bool {
758 let m = Identity(m);
759 let f = |x: i32| Identity(x.wrapping_mul(2));
760 let g = |x: i32| Identity(x.wrapping_add(1));
761 bind::<IdentityBrand, _, _, _>(bind::<IdentityBrand, _, _, _>(m, f), g)
762 == bind::<IdentityBrand, _, _, _>(m, |x| bind::<IdentityBrand, _, _, _>(f(x), g))
763 }
764
765 #[test]
769 fn map_test() {
770 assert_eq!(map::<IdentityBrand, _, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
771 }
772
773 #[test]
775 fn bind_test() {
776 assert_eq!(bind::<IdentityBrand, _, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
777 }
778
779 #[test]
781 fn fold_right_test() {
782 assert_eq!(
783 crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _, _>(
784 |x: i32, acc| x + acc,
785 0,
786 Identity(1)
787 ),
788 1
789 );
790 }
791
792 #[test]
794 fn fold_left_test() {
795 assert_eq!(
796 crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _, _>(
797 |acc, x: i32| acc + x,
798 0,
799 Identity(1)
800 ),
801 1
802 );
803 }
804
805 #[test]
807 fn traverse_test() {
808 assert_eq!(
809 crate::classes::traversable::traverse::<IdentityBrand, _, _, OptionBrand, _>(
810 |x: i32| Some(x + 1),
811 Identity(1)
812 ),
813 Some(Identity(2))
814 );
815 }
816
817 #[test]
821 fn par_fold_map_test() {
822 use crate::{brands::*, functions::*};
823
824 let x = Identity(1);
825 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
826 assert_eq!(par_fold_map::<ArcFnBrand, IdentityBrand, _, _>(f, x), "1".to_string());
827 }
828
829 #[test]
831 fn par_fold_right_test() {
832 use crate::{brands::*, functions::*};
833
834 let x = Identity(1);
835 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
836 assert_eq!(par_fold_right::<ArcFnBrand, IdentityBrand, _, _>(f, 10, x), 11);
837 }
838}