1#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::{
9 Apply,
10 brands::OptionBrand,
11 classes::{
12 Applicative,
13 ApplyFirst,
14 ApplySecond,
15 CloneableFn,
16 Compactable,
17 Filterable,
18 Foldable,
19 Functor,
20 Lift,
21 Monoid,
22 ParFoldable,
23 Pointed,
24 Semiapplicative,
25 Semimonad,
26 SendCloneableFn,
27 Traversable,
28 Witherable,
29 foldable_with_index::FoldableWithIndex,
30 functor_with_index::FunctorWithIndex,
31 traversable_with_index::TraversableWithIndex,
32 },
33 impl_kind,
34 kinds::*,
35 },
36 fp_macros::*,
37 };
38
39 impl_kind! {
40 for OptionBrand {
41 type Of<'a, A: 'a>: 'a = Option<A>;
42 }
43 }
44
45 impl Functor for OptionBrand {
46 #[document_signature]
50 #[document_type_parameters(
52 "The lifetime of the value.",
53 "The type of the value inside the option.",
54 "The type of the result of applying the function."
55 )]
56 #[document_parameters("The function to apply to the value.", "The option to map over.")]
58 #[document_returns(
60 "A new option containing the result of applying the function, or `None`."
61 )]
62 #[document_examples]
64 fn map<'a, A: 'a, B: 'a>(
76 func: impl Fn(A) -> B + 'a,
77 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
78 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
79 fa.map(func)
80 }
81 }
82
83 impl Lift for OptionBrand {
84 #[document_signature]
88 #[document_type_parameters(
90 "The lifetime of the values.",
91 "The type of the first option's value.",
92 "The type of the second option's value.",
93 "The return type of the function."
94 )]
95 #[document_parameters(
97 "The binary function to apply.",
98 "The first option.",
99 "The second option."
100 )]
101 #[document_returns("`Some(f(a, b))` if both options are `Some`, otherwise `None`.")]
103 #[document_examples]
104 fn lift2<'a, A, B, C>(
117 func: impl Fn(A, B) -> C + 'a,
118 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
119 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
120 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
121 where
122 A: 'a,
123 B: 'a,
124 C: 'a, {
125 fa.zip(fb).map(|(a, b)| func(a, b))
126 }
127 }
128
129 impl Pointed for OptionBrand {
130 #[document_signature]
134 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
136 #[document_parameters("The value to wrap.")]
138 #[document_returns("`Some(a)`.")]
140 #[document_examples]
142 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
153 Some(a)
154 }
155 }
156
157 impl ApplyFirst for OptionBrand {}
158 impl ApplySecond for OptionBrand {}
159
160 impl Semiapplicative for OptionBrand {
161 #[document_signature]
165 #[document_type_parameters(
167 "The lifetime of the values.",
168 "The brand of the cloneable function wrapper.",
169 "The type of the input value.",
170 "The type of the output value."
171 )]
172 #[document_parameters(
174 "The option containing the function.",
175 "The option containing the value."
176 )]
177 #[document_returns("`Some(f(a))` if both are `Some`, otherwise `None`.")]
179 #[document_examples]
180 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
194 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
195 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
196 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
197 match (ff, fa) {
198 (Some(f), Some(a)) => Some(f(a)),
199 _ => None,
200 }
201 }
202 }
203
204 impl Semimonad for OptionBrand {
205 #[document_signature]
209 #[document_type_parameters(
211 "The lifetime of the values.",
212 "The type of the result of the first computation.",
213 "The type of the result of the second computation."
214 )]
215 #[document_parameters(
217 "The first option.",
218 "The function to apply to the value inside the option."
219 )]
220 #[document_returns(
222 "The result of applying `f` to the value if `ma` is `Some`, otherwise `None`."
223 )]
224 #[document_examples]
225 fn bind<'a, A: 'a, B: 'a>(
237 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
238 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
239 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
240 ma.and_then(func)
241 }
242 }
243
244 impl Foldable for OptionBrand {
245 #[document_signature]
249 #[document_type_parameters(
251 "The lifetime of the values.",
252 "The brand of the cloneable function to use.",
253 "The type of the elements in the structure.",
254 "The type of the accumulator."
255 )]
256 #[document_parameters("The folding function.", "The initial value.", "The option to fold.")]
258 #[document_returns("`func(a, initial)` if `fa` is `Some(a)`, otherwise `initial`.")]
260 #[document_examples]
262 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
274 func: impl Fn(A, B) -> B + 'a,
275 initial: B,
276 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
277 ) -> B
278 where
279 FnBrand: CloneableFn + 'a, {
280 match fa {
281 Some(a) => func(a, initial),
282 None => initial,
283 }
284 }
285
286 #[document_signature]
290 #[document_type_parameters(
292 "The lifetime of the values.",
293 "The brand of the cloneable function to use.",
294 "The type of the elements in the structure.",
295 "The type of the accumulator."
296 )]
297 #[document_parameters(
299 "The function to apply to the accumulator and each element.",
300 "The initial value of the accumulator.",
301 "The option to fold."
302 )]
303 #[document_returns("`f(initial, a)` if `fa` is `Some(a)`, otherwise `initial`.")]
305 #[document_examples]
306 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
318 func: impl Fn(B, A) -> B + 'a,
319 initial: B,
320 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
321 ) -> B
322 where
323 FnBrand: CloneableFn + 'a, {
324 match fa {
325 Some(a) => func(initial, a),
326 None => initial,
327 }
328 }
329
330 #[document_signature]
334 #[document_type_parameters(
336 "The lifetime of the values.",
337 "The brand of the cloneable function to use.",
338 "The type of the elements in the structure.",
339 "The type of the monoid."
340 )]
341 #[document_parameters("The mapping function.", "The option to fold.")]
343 #[document_returns("`func(a)` if `fa` is `Some(a)`, otherwise `M::empty()`.")]
345 #[document_examples]
347 fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
359 func: impl Fn(A) -> M + 'a,
360 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
361 ) -> M
362 where
363 M: Monoid + 'a,
364 FnBrand: CloneableFn + 'a, {
365 match fa {
366 Some(a) => func(a),
367 None => M::empty(),
368 }
369 }
370 }
371
372 impl Traversable for OptionBrand {
373 #[document_signature]
377 #[document_type_parameters(
379 "The lifetime of the values.",
380 "The type of the elements in the traversable structure.",
381 "The type of the elements in the resulting traversable structure.",
382 "The applicative context."
383 )]
384 #[document_parameters(
386 "The function to apply to each element, returning a value in an applicative context.",
387 "The option to traverse."
388 )]
389 #[document_returns("The option wrapped in the applicative context.")]
391 #[document_examples]
392 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
404 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
405 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
406 ) -> 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>)>)
407 where
408 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
409 match ta {
410 Some(a) => F::map(|b| Some(b), func(a)),
411 None => F::pure(None),
412 }
413 }
414
415 #[document_signature]
419 #[document_type_parameters(
421 "The lifetime of the values.",
422 "The type of the elements in the traversable structure.",
423 "The applicative context."
424 )]
425 #[document_parameters("The option containing the applicative value.")]
427 #[document_returns("The result of the traversal.")]
429 #[document_examples]
434 fn sequence<'a, A: 'a + Clone, F: Applicative>(
446 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>)>)
447 ) -> 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>)>)
448 where
449 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
450 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
451 match ta {
452 Some(fa) => F::map(|a| Some(a), fa),
453 None => F::pure(None),
454 }
455 }
456 }
457
458 impl FunctorWithIndex<()> for OptionBrand {
459 #[document_signature]
461 #[document_type_parameters(
462 "The lifetime of the value.",
463 "The type of the value inside the option.",
464 "The type of the result of applying the function."
465 )]
466 #[document_parameters(
467 "The function to apply to the value and its index.",
468 "The option to map over."
469 )]
470 #[document_returns(
471 "A new option containing the result of applying the function, or `None`."
472 )]
473 #[document_examples]
474 fn map_with_index<'a, A: 'a, B: 'a>(
486 f: impl Fn((), A) -> B + 'a,
487 fa: Option<A>,
488 ) -> Option<B> {
489 fa.map(|a| f((), a))
490 }
491 }
492
493 impl FoldableWithIndex<()> for OptionBrand {
494 #[document_signature]
496 #[document_type_parameters(
497 "The lifetime of the value.",
498 "The type of the value inside the option.",
499 "The monoid type."
500 )]
501 #[document_parameters(
502 "The function to apply to the value and its index.",
503 "The option to fold."
504 )]
505 #[document_returns("The monoid value.")]
506 #[document_examples]
507 fn fold_map_with_index<'a, A: 'a, R: Monoid>(
520 f: impl Fn((), A) -> R + 'a,
521 fa: Option<A>,
522 ) -> R {
523 match fa {
524 Some(a) => f((), a),
525 None => R::empty(),
526 }
527 }
528 }
529
530 impl TraversableWithIndex<()> for OptionBrand {
531 #[document_signature]
533 #[document_type_parameters(
534 "The lifetime of the value.",
535 "The type of the value inside the option.",
536 "The type of the result.",
537 "The applicative context."
538 )]
539 #[document_parameters(
540 "The function to apply to the value and its index, returning a value in an applicative context.",
541 "The option to traverse."
542 )]
543 #[document_returns("The option wrapped in the applicative context.")]
544 #[document_examples]
545 fn traverse_with_index<'a, A: 'a, B: 'a + Clone, M: Applicative>(
560 f: impl Fn((), A) -> M::Of<'a, B> + 'a,
561 ta: Option<A>,
562 ) -> M::Of<'a, Option<B>> {
563 match ta {
564 Some(a) => M::map(|b| Some(b), f((), a)),
565 None => M::pure(None),
566 }
567 }
568 }
569
570 impl ParFoldable for OptionBrand {
571 #[document_signature]
575 #[document_type_parameters(
577 "The lifetime of the values.",
578 "The brand of the cloneable function wrapper.",
579 "The element type.",
580 "The monoid type."
581 )]
582 #[document_parameters("The mapping function.", "The option to fold.")]
584 #[document_returns("The combined monoid value.")]
586 #[document_examples]
588 fn par_fold_map<'a, FnBrand, A, M>(
601 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
602 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
603 ) -> M
604 where
605 FnBrand: 'a + SendCloneableFn,
606 A: 'a + Clone + Send + Sync,
607 M: Monoid + Send + Sync + 'a, {
608 match fa {
609 Some(a) => func(a),
610 None => M::empty(),
611 }
612 }
613 }
614
615 impl Compactable for OptionBrand {
616 #[document_signature]
620 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
622 #[document_parameters("The nested option.")]
624 #[document_returns("The flattened option.")]
626 #[document_examples]
628 fn compact<'a, A: 'a>(
640 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
641 'a,
642 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
643 >)
644 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
645 fa.flatten()
646 }
647
648 #[document_signature]
652 #[document_type_parameters(
654 "The lifetime of the values.",
655 "The type of the error value.",
656 "The type of the success value."
657 )]
658 #[document_parameters("The option of result.")]
660 #[document_returns("A pair of options.")]
662 #[document_examples]
664 fn separate<'a, E: 'a, O: 'a>(
677 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
678 ) -> (
679 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
680 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
681 ) {
682 match fa {
683 Some(Ok(o)) => (None, Some(o)),
684 Some(Err(e)) => (Some(e), None),
685 None => (None, None),
686 }
687 }
688 }
689
690 impl Filterable for OptionBrand {
691 #[document_signature]
695 #[document_type_parameters(
697 "The lifetime of the values.",
698 "The type of the input value.",
699 "The type of the error value.",
700 "The type of the success value."
701 )]
702 #[document_parameters("The function to apply.", "The option to partition.")]
704 #[document_returns("A pair of options.")]
706 #[document_examples]
708 fn partition_map<'a, A: 'a, E: 'a, O: 'a>(
722 func: impl Fn(A) -> Result<O, E> + 'a,
723 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
724 ) -> (
725 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
726 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
727 ) {
728 match fa {
729 Some(a) => match func(a) {
730 Ok(o) => (None, Some(o)),
731 Err(e) => (Some(e), None),
732 },
733 None => (None, None),
734 }
735 }
736
737 #[document_signature]
741 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
743 #[document_parameters("The predicate.", "The option to partition.")]
745 #[document_returns("A pair of options.")]
747 #[document_examples]
749 fn partition<'a, A: 'a + Clone>(
762 func: impl Fn(A) -> bool + 'a,
763 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
764 ) -> (
765 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
766 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
767 ) {
768 match fa {
769 Some(a) =>
770 if func(a.clone()) {
771 (None, Some(a))
772 } else {
773 (Some(a), None)
774 },
775 None => (None, None),
776 }
777 }
778
779 #[document_signature]
783 #[document_type_parameters(
785 "The lifetime of the values.",
786 "The type of the input value.",
787 "The type of the result of applying the function."
788 )]
789 #[document_parameters("The function to apply.", "The option to filter and map.")]
791 #[document_returns("The filtered and mapped option.")]
793 #[document_examples]
795 fn filter_map<'a, A: 'a, B: 'a>(
807 func: impl Fn(A) -> Option<B> + 'a,
808 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
809 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
810 fa.and_then(func)
811 }
812
813 #[document_signature]
817 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
819 #[document_parameters("The predicate.", "The option to filter.")]
821 #[document_returns("The filtered option.")]
823 #[document_examples]
825 fn filter<'a, A: 'a + Clone>(
837 func: impl Fn(A) -> bool + 'a,
838 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
839 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
840 fa.filter(|a| func(a.clone()))
841 }
842 }
843
844 impl Witherable for OptionBrand {
845 #[document_signature]
849 #[document_type_parameters(
851 "The lifetime of the values.",
852 "The applicative context.",
853 "The type of the elements in the input structure.",
854 "The type of the error values.",
855 "The type of the success values."
856 )]
857 #[document_parameters(
859 "The function to apply to each element, returning a `Result` in an applicative context.",
860 "The option to partition."
861 )]
862 #[document_returns("The partitioned option wrapped in the applicative context.")]
864 #[document_examples]
865 fn wilt<'a, M: Applicative, A: 'a + Clone, E: 'a + Clone, O: 'a + Clone>(
878 func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
879 + 'a,
880 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
881 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
882 'a,
883 (
884 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
885 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
886 ),
887 >)
888 where
889 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
890 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone, {
891 match ta {
892 Some(a) => M::map(
893 |res| match res {
894 Ok(o) => (None, Some(o)),
895 Err(e) => (Some(e), None),
896 },
897 func(a),
898 ),
899 None => M::pure((None, None)),
900 }
901 }
902
903 #[document_signature]
907 #[document_type_parameters(
909 "The lifetime of the values.",
910 "The applicative context.",
911 "The type of the elements in the input structure.",
912 "The type of the result of applying the function."
913 )]
914 #[document_parameters(
916 "The function to apply to each element, returning an `Option` in an applicative context.",
917 "The option to filter and map."
918 )]
919 #[document_returns("The filtered and mapped option wrapped in the applicative context.")]
921 #[document_examples]
922 fn wither<'a, M: Applicative, A: 'a + Clone, B: 'a + Clone>(
937 func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
938 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
939 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
940 'a,
941 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
942 >)
943 where
944 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
945 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone, {
946 match ta {
947 Some(a) => func(a),
948 None => M::pure(None),
949 }
950 }
951 }
952}
953
954#[cfg(test)]
955mod tests {
956
957 use {
958 crate::{
959 brands::*,
960 classes::CloneableFn,
961 functions::*,
962 },
963 quickcheck_macros::quickcheck,
964 };
965
966 #[quickcheck]
970 fn functor_identity(x: Option<i32>) -> bool {
971 map::<OptionBrand, _, _>(identity, x) == x
972 }
973
974 #[quickcheck]
976 fn functor_composition(x: Option<i32>) -> bool {
977 let f = |x: i32| x.wrapping_add(1);
978 let g = |x: i32| x.wrapping_mul(2);
979 map::<OptionBrand, _, _>(compose(f, g), x)
980 == map::<OptionBrand, _, _>(f, map::<OptionBrand, _, _>(g, x))
981 }
982
983 #[quickcheck]
987 fn applicative_identity(v: Option<i32>) -> bool {
988 apply::<RcFnBrand, OptionBrand, _, _>(
989 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
990 v,
991 ) == v
992 }
993
994 #[quickcheck]
996 fn applicative_homomorphism(x: i32) -> bool {
997 let f = |x: i32| x.wrapping_mul(2);
998 apply::<RcFnBrand, OptionBrand, _, _>(
999 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
1000 pure::<OptionBrand, _>(x),
1001 ) == pure::<OptionBrand, _>(f(x))
1002 }
1003
1004 #[quickcheck]
1006 fn applicative_composition(
1007 w: Option<i32>,
1008 u_is_some: bool,
1009 v_is_some: bool,
1010 ) -> bool {
1011 let v_fn = |x: i32| x.wrapping_mul(2);
1012 let u_fn = |x: i32| x.wrapping_add(1);
1013
1014 let v = if v_is_some {
1015 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn))
1016 } else {
1017 None
1018 };
1019 let u = if u_is_some {
1020 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn))
1021 } else {
1022 None
1023 };
1024
1025 let vw = apply::<RcFnBrand, OptionBrand, _, _>(v.clone(), w);
1027 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), vw);
1028
1029 let uv = match (u, v) {
1032 (Some(uf), Some(vf)) => {
1033 let composed = move |x| uf(vf(x));
1034 Some(<RcFnBrand as CloneableFn>::new(composed))
1035 }
1036 _ => None,
1037 };
1038
1039 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(uv, w);
1040
1041 lhs == rhs
1042 }
1043
1044 #[quickcheck]
1046 fn applicative_interchange(y: i32) -> bool {
1047 let f = |x: i32| x.wrapping_mul(2);
1049 let u = pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f));
1050
1051 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), pure::<OptionBrand, _>(y));
1052
1053 let rhs_fn =
1054 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1055 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(pure::<OptionBrand, _>(rhs_fn), u);
1056
1057 lhs == rhs
1058 }
1059
1060 #[quickcheck]
1064 fn monad_left_identity(a: i32) -> bool {
1065 let f = |x: i32| Some(x.wrapping_mul(2));
1066 bind::<OptionBrand, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
1067 }
1068
1069 #[quickcheck]
1071 fn monad_right_identity(m: Option<i32>) -> bool {
1072 bind::<OptionBrand, _, _>(m, pure::<OptionBrand, _>) == m
1073 }
1074
1075 #[quickcheck]
1077 fn monad_associativity(m: Option<i32>) -> bool {
1078 let f = |x: i32| Some(x.wrapping_mul(2));
1079 let g = |x: i32| Some(x.wrapping_add(1));
1080 bind::<OptionBrand, _, _>(bind::<OptionBrand, _, _>(m, f), g)
1081 == bind::<OptionBrand, _, _>(m, |x| bind::<OptionBrand, _, _>(f(x), g))
1082 }
1083
1084 #[test]
1088 fn map_none() {
1089 assert_eq!(map::<OptionBrand, _, _>(|x: i32| x + 1, None), None);
1090 }
1091
1092 #[test]
1094 fn bind_none() {
1095 assert_eq!(bind::<OptionBrand, _, _>(None, |x: i32| Some(x + 1)), None);
1096 }
1097
1098 #[test]
1100 fn bind_returning_none() {
1101 assert_eq!(bind::<OptionBrand, _, _>(Some(5), |_| None::<i32>), None);
1102 }
1103
1104 #[test]
1106 fn fold_right_none() {
1107 assert_eq!(
1108 crate::classes::foldable::fold_right::<RcFnBrand, OptionBrand, _, _>(
1109 |x: i32, acc| x + acc,
1110 0,
1111 None
1112 ),
1113 0
1114 );
1115 }
1116
1117 #[test]
1119 fn fold_left_none() {
1120 assert_eq!(
1121 crate::classes::foldable::fold_left::<RcFnBrand, OptionBrand, _, _>(
1122 |acc, x: i32| acc + x,
1123 0,
1124 None
1125 ),
1126 0
1127 );
1128 }
1129
1130 #[test]
1132 fn traverse_none() {
1133 assert_eq!(
1134 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
1135 |x: i32| Some(x + 1),
1136 None
1137 ),
1138 Some(None)
1139 );
1140 }
1141
1142 #[test]
1144 fn traverse_returning_none() {
1145 assert_eq!(
1146 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
1147 |_: i32| None::<i32>,
1148 Some(5)
1149 ),
1150 None
1151 );
1152 }
1153
1154 #[test]
1158 fn par_fold_map_none() {
1159 let x: Option<i32> = None;
1160 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1161 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "".to_string());
1162 }
1163
1164 #[test]
1166 fn par_fold_map_some() {
1167 let x = Some(5);
1168 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1169 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "5".to_string());
1170 }
1171
1172 #[test]
1174 fn par_fold_right_some() {
1175 let x = Some(5);
1176 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1177 assert_eq!(par_fold_right::<ArcFnBrand, OptionBrand, _, _>(f, 10, x), 15);
1178 }
1179
1180 #[quickcheck]
1184 fn filterable_filter_map_identity(x: Option<Option<i32>>) -> bool {
1185 filter_map::<OptionBrand, _, _>(identity, x) == compact::<OptionBrand, _>(x)
1186 }
1187
1188 #[quickcheck]
1190 fn filterable_filter_map_just(x: Option<i32>) -> bool {
1191 filter_map::<OptionBrand, _, _>(Some, x) == x
1192 }
1193
1194 #[quickcheck]
1196 fn filterable_filter_map_composition(x: Option<i32>) -> bool {
1197 let r = |i: i32| if i % 2 == 0 { Some(i) } else { None };
1198 let l = |i: i32| if i > 5 { Some(i) } else { None };
1199 let composed = |i| r(i).and_then(l);
1200
1201 filter_map::<OptionBrand, _, _>(composed, x)
1202 == filter_map::<OptionBrand, _, _>(l, filter_map::<OptionBrand, _, _>(r, x))
1203 }
1204
1205 #[quickcheck]
1207 fn filterable_filter_consistency(x: Option<i32>) -> bool {
1208 let p = |i: i32| i % 2 == 0;
1209 let maybe_bool = |i| if p(i) { Some(i) } else { None };
1210
1211 filter::<OptionBrand, _>(p, x) == filter_map::<OptionBrand, _, _>(maybe_bool, x)
1212 }
1213
1214 #[quickcheck]
1216 fn filterable_partition_map_identity(x: Option<Result<i32, i32>>) -> bool {
1217 partition_map::<OptionBrand, _, _, _>(identity, x) == separate::<OptionBrand, _, _>(x)
1218 }
1219
1220 #[quickcheck]
1222 fn filterable_partition_map_right_identity(x: Option<i32>) -> bool {
1223 let (_, oks) = partition_map::<OptionBrand, _, _, _>(Ok::<_, i32>, x);
1224 oks == x
1225 }
1226
1227 #[quickcheck]
1229 fn filterable_partition_map_left_identity(x: Option<i32>) -> bool {
1230 let (errs, _) = partition_map::<OptionBrand, _, _, _>(Err::<i32, _>, x);
1231 errs == x
1232 }
1233
1234 #[quickcheck]
1236 fn filterable_partition_consistency(x: Option<i32>) -> bool {
1237 let p = |i: i32| i % 2 == 0;
1238 let either_bool = |i| if p(i) { Ok(i) } else { Err(i) };
1239
1240 let (not_satisfied, satisfied) = partition::<OptionBrand, _>(p, x);
1241 let (errs, oks) = partition_map::<OptionBrand, _, _, _>(either_bool, x);
1242
1243 satisfied == oks && not_satisfied == errs
1244 }
1245
1246 #[quickcheck]
1250 fn witherable_identity(x: Option<i32>) -> bool {
1251 wither::<OptionBrand, OptionBrand, _, _>(|i| Some(Some(i)), x) == Some(x)
1252 }
1253
1254 #[quickcheck]
1256 fn witherable_wilt_consistency(x: Option<i32>) -> bool {
1257 let p = |i: i32| Some(if i % 2 == 0 { Ok(i) } else { Err(i) });
1258
1259 let lhs = wilt::<OptionBrand, OptionBrand, _, _, _>(p, x);
1260 let rhs = map::<OptionBrand, _, _>(
1261 separate::<OptionBrand, _, _>,
1262 traverse::<OptionBrand, _, _, OptionBrand>(p, x),
1263 );
1264
1265 lhs == rhs
1266 }
1267
1268 #[quickcheck]
1270 fn witherable_wither_consistency(x: Option<i32>) -> bool {
1271 let p = |i: i32| Some(if i % 2 == 0 { Some(i) } else { None });
1272
1273 let lhs = wither::<OptionBrand, OptionBrand, _, _>(p, x);
1274 let rhs = map::<OptionBrand, _, _>(
1275 compact::<OptionBrand, _>,
1276 traverse::<OptionBrand, _, _, OptionBrand>(p, x),
1277 );
1278
1279 lhs == rhs
1280 }
1281
1282 #[test]
1286 fn compact_some_none() {
1287 assert_eq!(compact::<OptionBrand, _>(Some(None::<i32>)), None);
1288 }
1289
1290 #[test]
1292 fn compact_some_some() {
1293 assert_eq!(compact::<OptionBrand, _>(Some(Some(5))), Some(5));
1294 }
1295
1296 #[test]
1298 fn compact_none() {
1299 assert_eq!(compact::<OptionBrand, _>(None::<Option<i32>>), None);
1300 }
1301
1302 #[test]
1304 fn separate_some_ok() {
1305 let (errs, oks) = separate::<OptionBrand, _, _>(Some(Ok::<i32, &str>(5)));
1306 assert_eq!(oks, Some(5));
1307 assert_eq!(errs, None);
1308 }
1309
1310 #[test]
1312 fn separate_some_err() {
1313 let (errs, oks) = separate::<OptionBrand, _, _>(Some(Err::<i32, &str>("error")));
1314 assert_eq!(oks, None);
1315 assert_eq!(errs, Some("error"));
1316 }
1317
1318 #[test]
1320 fn separate_none() {
1321 let (errs, oks) = separate::<OptionBrand, _, _>(None::<Result<i32, &str>>);
1322 assert_eq!(oks, None);
1323 assert_eq!(errs, None);
1324 }
1325
1326 #[test]
1328 fn partition_map_none() {
1329 let (errs, oks) =
1330 partition_map::<OptionBrand, _, _, _>(|x: i32| Ok::<i32, i32>(x), None::<i32>);
1331 assert_eq!(oks, None);
1332 assert_eq!(errs, None);
1333 }
1334
1335 #[test]
1337 fn partition_none() {
1338 let (not_satisfied, satisfied) = partition::<OptionBrand, _>(|x: i32| x > 0, None::<i32>);
1339 assert_eq!(satisfied, None);
1340 assert_eq!(not_satisfied, None);
1341 }
1342
1343 #[test]
1345 fn filter_map_none() {
1346 assert_eq!(filter_map::<OptionBrand, _, _>(|x: i32| Some(x), None::<i32>), None);
1347 }
1348
1349 #[test]
1351 fn filter_none() {
1352 assert_eq!(filter::<OptionBrand, _>(|x: i32| x > 0, None::<i32>), None);
1353 }
1354
1355 #[test]
1357 fn wilt_none() {
1358 let res = wilt::<OptionBrand, OptionBrand, _, _, _>(
1359 |x: i32| Some(Ok::<i32, i32>(x)),
1360 None::<i32>,
1361 );
1362 assert_eq!(res, Some((None, None)));
1363 }
1364
1365 #[test]
1367 fn wither_none() {
1368 let res = wither::<OptionBrand, OptionBrand, _, _>(|x: i32| Some(Some(x)), None::<i32>);
1369 assert_eq!(res, Some(None));
1370 }
1371}