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 impl Functor for IdentityBrand {
61 #[document_signature]
65 #[document_type_parameters(
67 "The lifetime of the value.",
68 "The type of the value inside the identity.",
69 "The type of the result of applying the function."
70 )]
71 #[document_parameters("The function to apply.", "The identity to map over.")]
73 #[document_returns("A new identity containing the result of applying the function.")]
75 #[document_examples]
77 fn map<'a, A: 'a, B: 'a>(
90 func: impl Fn(A) -> B + 'a,
91 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
92 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
93 Identity(func(fa.0))
94 }
95 }
96
97 impl Lift for IdentityBrand {
98 #[document_signature]
102 #[document_type_parameters(
104 "The lifetime of the values.",
105 "The type of the first identity's value.",
106 "The type of the second identity's value.",
107 "The return type of the function."
108 )]
109 #[document_parameters(
111 "The binary function to apply.",
112 "The first identity.",
113 "The second identity."
114 )]
115 #[document_returns("A new identity containing the result of applying the function.")]
117 #[document_examples]
118 fn lift2<'a, A, B, C>(
132 func: impl Fn(A, B) -> C + 'a,
133 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
134 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
135 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
136 where
137 A: 'a,
138 B: 'a,
139 C: 'a, {
140 Identity(func(fa.0, fb.0))
141 }
142 }
143
144 impl Pointed for IdentityBrand {
145 #[document_signature]
149 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
151 #[document_parameters("The value to wrap.")]
153 #[document_returns("An identity containing the value.")]
155 #[document_examples]
157 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
169 Identity(a)
170 }
171 }
172
173 impl ApplyFirst for IdentityBrand {}
174 impl ApplySecond for IdentityBrand {}
175
176 impl Semiapplicative for IdentityBrand {
177 #[document_signature]
181 #[document_type_parameters(
183 "The lifetime of the values.",
184 "The brand of the cloneable function wrapper.",
185 "The type of the input value.",
186 "The type of the output value."
187 )]
188 #[document_parameters(
190 "The identity containing the function.",
191 "The identity containing the value."
192 )]
193 #[document_returns("A new identity containing the result of applying the function.")]
195 #[document_examples]
196 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
210 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
211 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
212 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
213 Identity(ff.0(fa.0))
214 }
215 }
216
217 impl Semimonad for IdentityBrand {
218 #[document_signature]
222 #[document_type_parameters(
224 "The lifetime of the values.",
225 "The type of the result of the first computation.",
226 "The type of the result of the second computation."
227 )]
228 #[document_parameters(
230 "The first identity.",
231 "The function to apply to the value inside the identity."
232 )]
233 #[document_returns("The result of applying `f` to the value.")]
235 #[document_examples]
236 fn bind<'a, A: 'a, B: 'a>(
249 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
250 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
251 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
252 func(ma.0)
253 }
254 }
255
256 impl Foldable for IdentityBrand {
257 #[document_signature]
261 #[document_type_parameters(
263 "The lifetime of the values.",
264 "The brand of the cloneable function to use.",
265 "The type of the elements in the structure.",
266 "The type of the accumulator."
267 )]
268 #[document_parameters(
270 "The function to apply to each element and the accumulator.",
271 "The initial value of the accumulator.",
272 "The identity to fold."
273 )]
274 #[document_returns("The final accumulator value.")]
276 #[document_examples]
277 fn fold_right<'a, FnBrand, A: 'a, B: 'a>(
290 func: impl Fn(A, B) -> B + 'a,
291 initial: B,
292 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
293 ) -> B
294 where
295 FnBrand: CloneableFn + 'a, {
296 func(fa.0, initial)
297 }
298
299 #[document_signature]
303 #[document_type_parameters(
305 "The lifetime of the values.",
306 "The brand of the cloneable function to use.",
307 "The type of the elements in the structure.",
308 "The type of the accumulator."
309 )]
310 #[document_parameters(
312 "The function to apply to the accumulator and each element.",
313 "The initial value of the accumulator.",
314 "The structure to fold."
315 )]
316 #[document_returns("The final accumulator value.")]
318 #[document_examples]
319 fn fold_left<'a, FnBrand, A: 'a, B: 'a>(
332 func: impl Fn(B, A) -> B + 'a,
333 initial: B,
334 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
335 ) -> B
336 where
337 FnBrand: CloneableFn + 'a, {
338 func(initial, fa.0)
339 }
340
341 #[document_signature]
345 #[document_type_parameters(
347 "The lifetime of the values.",
348 "The brand of the cloneable function to use.",
349 "The type of the elements in the structure.",
350 "The type of the monoid."
351 )]
352 #[document_parameters("The mapping function.", "The identity to fold.")]
354 #[document_returns("The monoid value.")]
356 #[document_examples]
358 fn fold_map<'a, FnBrand, A: 'a, M>(
371 func: impl Fn(A) -> M + 'a,
372 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
373 ) -> M
374 where
375 M: Monoid + 'a,
376 FnBrand: CloneableFn + 'a, {
377 func(fa.0)
378 }
379 }
380
381 impl Traversable for IdentityBrand {
382 #[document_signature]
386 #[document_type_parameters(
388 "The lifetime of the values.",
389 "The type of the elements in the traversable structure.",
390 "The type of the elements in the resulting traversable structure.",
391 "The applicative context."
392 )]
393 #[document_parameters(
395 "The function to apply to each element, returning a value in an applicative context.",
396 "The identity to traverse."
397 )]
398 #[document_returns("The identity wrapped in the applicative context.")]
400 #[document_examples]
401 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
414 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
415 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
416 ) -> 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>)>)
417 where
418 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
419 F::map(|b| Identity(b), func(ta.0))
420 }
421
422 #[document_signature]
426 #[document_type_parameters(
428 "The lifetime of the values.",
429 "The type of the elements in the traversable structure.",
430 "The applicative context."
431 )]
432 #[document_parameters("The identity containing the applicative value.")]
434 #[document_returns("The result of the traversal.")]
436 #[document_examples]
441 fn sequence<'a, A: 'a + Clone, F: Applicative>(
454 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>)>)
455 ) -> 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>)>)
456 where
457 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
458 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
459 F::map(|a| Identity(a), ta.0)
460 }
461 }
462
463 impl ParFoldable for IdentityBrand {
464 #[document_signature]
468 #[document_type_parameters(
470 "The lifetime of the values.",
471 "The brand of the cloneable function wrapper.",
472 "The element type.",
473 "The monoid type."
474 )]
475 #[document_parameters("The mapping function.", "The identity to fold.")]
477 #[document_returns("The combined monoid value.")]
479 #[document_examples]
481 fn par_fold_map<'a, FnBrand, A, M>(
495 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
496 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
497 ) -> M
498 where
499 FnBrand: 'a + SendCloneableFn,
500 A: 'a + Clone + Send + Sync,
501 M: Monoid + Send + Sync + 'a, {
502 func(fa.0)
503 }
504
505 #[document_signature]
509 #[document_type_parameters(
511 "The lifetime of the values.",
512 "The brand of the cloneable function wrapper.",
513 "The element type.",
514 "The accumulator type."
515 )]
516 #[document_parameters(
518 "The thread-safe function to apply to each element and the accumulator.",
519 "The initial value of the accumulator.",
520 "The identity to fold."
521 )]
522 #[document_returns("The final accumulator value.")]
524 #[document_examples]
525 fn par_fold_right<'a, FnBrand, A, B>(
539 func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
540 initial: B,
541 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
542 ) -> B
543 where
544 FnBrand: 'a + SendCloneableFn,
545 A: 'a + Clone + Send + Sync,
546 B: Send + Sync + 'a, {
547 func((fa.0, initial))
548 }
549 }
550}
551pub use inner::*;
552
553#[cfg(test)]
554mod tests {
555 use {
556 super::inner::Identity,
557 crate::{
558 brands::{
559 IdentityBrand,
560 OptionBrand,
561 RcFnBrand,
562 },
563 classes::{
564 cloneable_fn::CloneableFn,
565 functor::map,
566 pointed::pure,
567 semiapplicative::apply,
568 semimonad::bind,
569 },
570 functions::{
571 compose,
572 identity,
573 },
574 },
575 quickcheck_macros::quickcheck,
576 };
577
578 #[quickcheck]
582 fn functor_identity(x: i32) -> bool {
583 let x = Identity(x);
584 map::<IdentityBrand, _, _>(identity, x) == x
585 }
586
587 #[quickcheck]
589 fn functor_composition(x: i32) -> bool {
590 let x = Identity(x);
591 let f = |x: i32| x.wrapping_add(1);
592 let g = |x: i32| x.wrapping_mul(2);
593 map::<IdentityBrand, _, _>(compose(f, g), x)
594 == map::<IdentityBrand, _, _>(f, map::<IdentityBrand, _, _>(g, x))
595 }
596
597 #[quickcheck]
601 fn applicative_identity(v: i32) -> bool {
602 let v = Identity(v);
603 apply::<RcFnBrand, IdentityBrand, _, _>(
604 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
605 v,
606 ) == v
607 }
608
609 #[quickcheck]
611 fn applicative_homomorphism(x: i32) -> bool {
612 let f = |x: i32| x.wrapping_mul(2);
613 apply::<RcFnBrand, IdentityBrand, _, _>(
614 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
615 pure::<IdentityBrand, _>(x),
616 ) == pure::<IdentityBrand, _>(f(x))
617 }
618
619 #[quickcheck]
621 fn applicative_composition(
622 w: i32,
623 u_val: i32,
624 v_val: i32,
625 ) -> bool {
626 let w = Identity(w);
627 let v_fn = move |x: i32| x.wrapping_mul(v_val);
628 let u_fn = move |x: i32| x.wrapping_add(u_val);
629
630 let v = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
631 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
632
633 let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w);
635 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
636
637 let composed = move |x| u_fn(v_fn(x));
640 let uv = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(composed));
641
642 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
643
644 lhs == rhs
645 }
646
647 #[quickcheck]
649 fn applicative_interchange(y: i32) -> bool {
650 let f = |x: i32| x.wrapping_mul(2);
652 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f));
653
654 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
655
656 let rhs_fn =
657 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
658 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
659
660 lhs == rhs
661 }
662
663 #[quickcheck]
667 fn monad_left_identity(a: i32) -> bool {
668 let f = |x: i32| Identity(x.wrapping_mul(2));
669 bind::<IdentityBrand, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
670 }
671
672 #[quickcheck]
674 fn monad_right_identity(m: i32) -> bool {
675 let m = Identity(m);
676 bind::<IdentityBrand, _, _>(m, pure::<IdentityBrand, _>) == m
677 }
678
679 #[quickcheck]
681 fn monad_associativity(m: i32) -> bool {
682 let m = Identity(m);
683 let f = |x: i32| Identity(x.wrapping_mul(2));
684 let g = |x: i32| Identity(x.wrapping_add(1));
685 bind::<IdentityBrand, _, _>(bind::<IdentityBrand, _, _>(m, f), g)
686 == bind::<IdentityBrand, _, _>(m, |x| bind::<IdentityBrand, _, _>(f(x), g))
687 }
688
689 #[test]
693 fn map_test() {
694 assert_eq!(map::<IdentityBrand, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
695 }
696
697 #[test]
699 fn bind_test() {
700 assert_eq!(bind::<IdentityBrand, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
701 }
702
703 #[test]
705 fn fold_right_test() {
706 assert_eq!(
707 crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _>(
708 |x: i32, acc| x + acc,
709 0,
710 Identity(1)
711 ),
712 1
713 );
714 }
715
716 #[test]
718 fn fold_left_test() {
719 assert_eq!(
720 crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _>(
721 |acc, x: i32| acc + x,
722 0,
723 Identity(1)
724 ),
725 1
726 );
727 }
728
729 #[test]
731 fn traverse_test() {
732 assert_eq!(
733 crate::classes::traversable::traverse::<IdentityBrand, _, _, OptionBrand>(
734 |x: i32| Some(x + 1),
735 Identity(1)
736 ),
737 Some(Identity(2))
738 );
739 }
740
741 #[test]
745 fn par_fold_map_test() {
746 use crate::{
747 brands::*,
748 functions::*,
749 };
750
751 let x = Identity(1);
752 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
753 assert_eq!(par_fold_map::<ArcFnBrand, IdentityBrand, _, _>(f, x), "1".to_string());
754 }
755
756 #[test]
758 fn par_fold_right_test() {
759 use crate::{
760 brands::*,
761 functions::*,
762 };
763
764 let x = Identity(1);
765 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
766 assert_eq!(par_fold_right::<ArcFnBrand, IdentityBrand, _, _>(f, 10, x), 11);
767 }
768}