1#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::{
9 Apply,
10 brands::OptionBrand,
11 classes::{
12 Alt,
13 Applicative,
14 ApplyFirst,
15 ApplySecond,
16 CloneableFn,
17 Compactable,
18 Filterable,
19 Foldable,
20 Functor,
21 Lift,
22 Monoid,
23 Plus,
24 Pointed,
25 Semiapplicative,
26 Semimonad,
27 Traversable,
28 Witherable,
29 foldable_with_index::FoldableWithIndex,
30 functor_with_index::FunctorWithIndex,
31 traversable_with_index::TraversableWithIndex,
32 with_index::WithIndex,
33 },
34 impl_kind,
35 kinds::*,
36 },
37 fp_macros::*,
38 };
39
40 impl_kind! {
41 for OptionBrand {
42 type Of<'a, A: 'a>: 'a = Option<A>;
43 }
44 }
45
46 impl Functor for OptionBrand {
47 #[document_signature]
51 #[document_type_parameters(
53 "The lifetime of the value.",
54 "The type of the value inside the option.",
55 "The type of the result of applying the function."
56 )]
57 #[document_parameters("The function to apply to the value.", "The option to map over.")]
59 #[document_returns(
61 "A new option containing the result of applying the function, or `None`."
62 )]
63 #[document_examples]
65 fn map<'a, A: 'a, B: 'a>(
77 func: impl Fn(A) -> B + 'a,
78 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
79 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
80 fa.map(func)
81 }
82 }
83
84 impl Lift for OptionBrand {
85 #[document_signature]
89 #[document_type_parameters(
91 "The lifetime of the values.",
92 "The type of the first option's value.",
93 "The type of the second option's value.",
94 "The return type of the function."
95 )]
96 #[document_parameters(
98 "The binary function to apply.",
99 "The first option.",
100 "The second option."
101 )]
102 #[document_returns("`Some(f(a, b))` if both options are `Some`, otherwise `None`.")]
104 #[document_examples]
105 fn lift2<'a, A, B, C>(
118 func: impl Fn(A, B) -> C + 'a,
119 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
120 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
121 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
122 where
123 A: 'a,
124 B: 'a,
125 C: 'a, {
126 fa.zip(fb).map(|(a, b)| func(a, b))
127 }
128 }
129
130 impl Pointed for OptionBrand {
131 #[document_signature]
135 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
137 #[document_parameters("The value to wrap.")]
139 #[document_returns("`Some(a)`.")]
141 #[document_examples]
143 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
154 Some(a)
155 }
156 }
157
158 impl ApplyFirst for OptionBrand {}
159 impl ApplySecond for OptionBrand {}
160
161 impl Semiapplicative for OptionBrand {
162 #[document_signature]
166 #[document_type_parameters(
168 "The lifetime of the values.",
169 "The brand of the cloneable function wrapper.",
170 "The type of the input value.",
171 "The type of the output value."
172 )]
173 #[document_parameters(
175 "The option containing the function.",
176 "The option containing the value."
177 )]
178 #[document_returns("`Some(f(a))` if both are `Some`, otherwise `None`.")]
180 #[document_examples]
181 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
195 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
196 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
197 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
198 match (ff, fa) {
199 (Some(f), Some(a)) => Some(f(a)),
200 _ => None,
201 }
202 }
203 }
204
205 impl Semimonad for OptionBrand {
206 #[document_signature]
210 #[document_type_parameters(
212 "The lifetime of the values.",
213 "The type of the result of the first computation.",
214 "The type of the result of the second computation."
215 )]
216 #[document_parameters(
218 "The first option.",
219 "The function to apply to the value inside the option."
220 )]
221 #[document_returns(
223 "The result of applying `f` to the value if `ma` is `Some`, otherwise `None`."
224 )]
225 #[document_examples]
226 fn bind<'a, A: 'a, B: 'a>(
238 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
239 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
240 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
241 ma.and_then(func)
242 }
243 }
244
245 impl Alt for OptionBrand {
246 #[document_signature]
250 #[document_type_parameters("The lifetime of the values.", "The type of the value.")]
252 #[document_parameters("The first option.", "The second option.")]
254 #[document_returns("The first `Some` value, or `None`.")]
256 #[document_examples]
257 fn alt<'a, A: 'a>(
270 fa1: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
271 fa2: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
272 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
273 fa1.or(fa2)
274 }
275 }
276
277 impl Plus for OptionBrand {
278 #[document_signature]
280 #[document_type_parameters("The lifetime of the value.", "The type of the value.")]
282 #[document_returns("`None`.")]
284 #[document_examples]
285 fn empty<'a, A: 'a>() -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
296 None
297 }
298 }
299
300 impl Foldable for OptionBrand {
301 #[document_signature]
305 #[document_type_parameters(
307 "The lifetime of the values.",
308 "The brand of the cloneable function to use.",
309 "The type of the elements in the structure.",
310 "The type of the accumulator."
311 )]
312 #[document_parameters("The folding function.", "The initial value.", "The option to fold.")]
314 #[document_returns("`func(a, initial)` if `fa` is `Some(a)`, otherwise `initial`.")]
316 #[document_examples]
318 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
330 func: impl Fn(A, B) -> B + 'a,
331 initial: B,
332 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
333 ) -> B
334 where
335 FnBrand: CloneableFn + 'a, {
336 match fa {
337 Some(a) => func(a, initial),
338 None => initial,
339 }
340 }
341
342 #[document_signature]
346 #[document_type_parameters(
348 "The lifetime of the values.",
349 "The brand of the cloneable function to use.",
350 "The type of the elements in the structure.",
351 "The type of the accumulator."
352 )]
353 #[document_parameters(
355 "The function to apply to the accumulator and each element.",
356 "The initial value of the accumulator.",
357 "The option to fold."
358 )]
359 #[document_returns("`f(initial, a)` if `fa` is `Some(a)`, otherwise `initial`.")]
361 #[document_examples]
362 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
374 func: impl Fn(B, A) -> B + 'a,
375 initial: B,
376 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
377 ) -> B
378 where
379 FnBrand: CloneableFn + 'a, {
380 match fa {
381 Some(a) => func(initial, a),
382 None => initial,
383 }
384 }
385
386 #[document_signature]
390 #[document_type_parameters(
392 "The lifetime of the values.",
393 "The brand of the cloneable function to use.",
394 "The type of the elements in the structure.",
395 "The type of the monoid."
396 )]
397 #[document_parameters("The mapping function.", "The option to fold.")]
399 #[document_returns("`func(a)` if `fa` is `Some(a)`, otherwise `M::empty()`.")]
401 #[document_examples]
403 fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
415 func: impl Fn(A) -> M + 'a,
416 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
417 ) -> M
418 where
419 M: Monoid + 'a,
420 FnBrand: CloneableFn + 'a, {
421 match fa {
422 Some(a) => func(a),
423 None => M::empty(),
424 }
425 }
426 }
427
428 impl Traversable for OptionBrand {
429 #[document_signature]
433 #[document_type_parameters(
435 "The lifetime of the values.",
436 "The type of the elements in the traversable structure.",
437 "The type of the elements in the resulting traversable structure.",
438 "The applicative context."
439 )]
440 #[document_parameters(
442 "The function to apply to each element, returning a value in an applicative context.",
443 "The option to traverse."
444 )]
445 #[document_returns("The option wrapped in the applicative context.")]
447 #[document_examples]
448 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
460 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
461 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
462 ) -> 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>)>)
463 where
464 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
465 match ta {
466 Some(a) => F::map(|b| Some(b), func(a)),
467 None => F::pure(None),
468 }
469 }
470
471 #[document_signature]
475 #[document_type_parameters(
477 "The lifetime of the values.",
478 "The type of the elements in the traversable structure.",
479 "The applicative context."
480 )]
481 #[document_parameters("The option containing the applicative value.")]
483 #[document_returns("The result of the traversal.")]
485 #[document_examples]
490 fn sequence<'a, A: 'a + Clone, F: Applicative>(
502 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>)>)
503 ) -> 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>)>)
504 where
505 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
506 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
507 match ta {
508 Some(fa) => F::map(|a| Some(a), fa),
509 None => F::pure(None),
510 }
511 }
512 }
513
514 impl WithIndex for OptionBrand {
515 type Index = ();
516 }
517
518 impl FunctorWithIndex for OptionBrand {
519 #[document_signature]
521 #[document_type_parameters(
522 "The lifetime of the value.",
523 "The type of the value inside the option.",
524 "The type of the result of applying the function."
525 )]
526 #[document_parameters(
527 "The function to apply to the value and its index.",
528 "The option to map over."
529 )]
530 #[document_returns(
531 "A new option containing the result of applying the function, or `None`."
532 )]
533 #[document_examples]
534 fn map_with_index<'a, A: 'a, B: 'a>(
546 f: impl Fn((), A) -> B + 'a,
547 fa: Option<A>,
548 ) -> Option<B> {
549 fa.map(|a| f((), a))
550 }
551 }
552
553 impl FoldableWithIndex for OptionBrand {
554 #[document_signature]
556 #[document_type_parameters(
557 "The lifetime of the value.",
558 "The type of the value inside the option.",
559 "The monoid type."
560 )]
561 #[document_parameters(
562 "The function to apply to the value and its index.",
563 "The option to fold."
564 )]
565 #[document_returns("The monoid value.")]
566 #[document_examples]
567 fn fold_map_with_index<'a, A: 'a, R: Monoid>(
579 f: impl Fn((), A) -> R + 'a,
580 fa: Option<A>,
581 ) -> R {
582 match fa {
583 Some(a) => f((), a),
584 None => R::empty(),
585 }
586 }
587 }
588
589 impl TraversableWithIndex for OptionBrand {
590 #[document_signature]
592 #[document_type_parameters(
593 "The lifetime of the value.",
594 "The type of the value inside the option.",
595 "The type of the result.",
596 "The applicative context."
597 )]
598 #[document_parameters(
599 "The function to apply to the value and its index, returning a value in an applicative context.",
600 "The option to traverse."
601 )]
602 #[document_returns("The option wrapped in the applicative context.")]
603 #[document_examples]
604 fn traverse_with_index<'a, A: 'a, B: 'a + Clone, M: Applicative>(
619 f: impl Fn((), A) -> M::Of<'a, B> + 'a,
620 ta: Option<A>,
621 ) -> M::Of<'a, Option<B>> {
622 match ta {
623 Some(a) => M::map(|b| Some(b), f((), a)),
624 None => M::pure(None),
625 }
626 }
627 }
628
629 impl Compactable for OptionBrand {
630 #[document_signature]
634 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
636 #[document_parameters("The nested option.")]
638 #[document_returns("The flattened option.")]
640 #[document_examples]
642 fn compact<'a, A: 'a>(
654 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
655 'a,
656 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
657 >)
658 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
659 fa.flatten()
660 }
661
662 #[document_signature]
666 #[document_type_parameters(
668 "The lifetime of the values.",
669 "The type of the error value.",
670 "The type of the success value."
671 )]
672 #[document_parameters("The option of result.")]
674 #[document_returns("A pair of options.")]
676 #[document_examples]
678 fn separate<'a, E: 'a, O: 'a>(
691 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
692 ) -> (
693 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
694 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
695 ) {
696 match fa {
697 Some(Ok(o)) => (None, Some(o)),
698 Some(Err(e)) => (Some(e), None),
699 None => (None, None),
700 }
701 }
702 }
703
704 impl Filterable for OptionBrand {
705 #[document_signature]
709 #[document_type_parameters(
711 "The lifetime of the values.",
712 "The type of the input value.",
713 "The type of the error value.",
714 "The type of the success value."
715 )]
716 #[document_parameters("The function to apply.", "The option to partition.")]
718 #[document_returns("A pair of options.")]
720 #[document_examples]
722 fn partition_map<'a, A: 'a, E: 'a, O: 'a>(
736 func: impl Fn(A) -> Result<O, E> + 'a,
737 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
738 ) -> (
739 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
740 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
741 ) {
742 match fa {
743 Some(a) => match func(a) {
744 Ok(o) => (None, Some(o)),
745 Err(e) => (Some(e), None),
746 },
747 None => (None, None),
748 }
749 }
750
751 #[document_signature]
755 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
757 #[document_parameters("The predicate.", "The option to partition.")]
759 #[document_returns("A pair of options.")]
761 #[document_examples]
763 fn partition<'a, A: 'a + Clone>(
776 func: impl Fn(A) -> bool + 'a,
777 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
778 ) -> (
779 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
780 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
781 ) {
782 match fa {
783 Some(a) =>
784 if func(a.clone()) {
785 (None, Some(a))
786 } else {
787 (Some(a), None)
788 },
789 None => (None, None),
790 }
791 }
792
793 #[document_signature]
797 #[document_type_parameters(
799 "The lifetime of the values.",
800 "The type of the input value.",
801 "The type of the result of applying the function."
802 )]
803 #[document_parameters("The function to apply.", "The option to filter and map.")]
805 #[document_returns("The filtered and mapped option.")]
807 #[document_examples]
809 fn filter_map<'a, A: 'a, B: 'a>(
821 func: impl Fn(A) -> Option<B> + 'a,
822 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
823 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
824 fa.and_then(func)
825 }
826
827 #[document_signature]
831 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
833 #[document_parameters("The predicate.", "The option to filter.")]
835 #[document_returns("The filtered option.")]
837 #[document_examples]
839 fn filter<'a, A: 'a + Clone>(
851 func: impl Fn(A) -> bool + 'a,
852 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
853 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
854 fa.filter(|a| func(a.clone()))
855 }
856 }
857
858 impl Witherable for OptionBrand {
859 #[document_signature]
863 #[document_type_parameters(
865 "The lifetime of the values.",
866 "The applicative context.",
867 "The type of the elements in the input structure.",
868 "The type of the error values.",
869 "The type of the success values."
870 )]
871 #[document_parameters(
873 "The function to apply to each element, returning a `Result` in an applicative context.",
874 "The option to partition."
875 )]
876 #[document_returns("The partitioned option wrapped in the applicative context.")]
878 #[document_examples]
879 fn wilt<'a, M: Applicative, A: 'a + Clone, E: 'a + Clone, O: 'a + Clone>(
892 func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
893 + 'a,
894 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
895 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
896 'a,
897 (
898 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
899 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
900 ),
901 >)
902 where
903 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
904 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone, {
905 match ta {
906 Some(a) => M::map(
907 |res| match res {
908 Ok(o) => (None, Some(o)),
909 Err(e) => (Some(e), None),
910 },
911 func(a),
912 ),
913 None => M::pure((None, None)),
914 }
915 }
916
917 #[document_signature]
921 #[document_type_parameters(
923 "The lifetime of the values.",
924 "The applicative context.",
925 "The type of the elements in the input structure.",
926 "The type of the result of applying the function."
927 )]
928 #[document_parameters(
930 "The function to apply to each element, returning an `Option` in an applicative context.",
931 "The option to filter and map."
932 )]
933 #[document_returns("The filtered and mapped option wrapped in the applicative context.")]
935 #[document_examples]
936 fn wither<'a, M: Applicative, A: 'a + Clone, B: 'a + Clone>(
951 func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
952 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
953 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
954 'a,
955 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
956 >)
957 where
958 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
959 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone, {
960 match ta {
961 Some(a) => func(a),
962 None => M::pure(None),
963 }
964 }
965 }
966}
967
968#[cfg(test)]
969mod tests {
970
971 use {
972 crate::{
973 brands::*,
974 classes::CloneableFn,
975 functions::*,
976 },
977 quickcheck_macros::quickcheck,
978 };
979
980 #[quickcheck]
984 fn functor_identity(x: Option<i32>) -> bool {
985 map::<OptionBrand, _, _>(identity, x) == x
986 }
987
988 #[quickcheck]
990 fn functor_composition(x: Option<i32>) -> bool {
991 let f = |x: i32| x.wrapping_add(1);
992 let g = |x: i32| x.wrapping_mul(2);
993 map::<OptionBrand, _, _>(compose(f, g), x)
994 == map::<OptionBrand, _, _>(f, map::<OptionBrand, _, _>(g, x))
995 }
996
997 #[quickcheck]
1001 fn applicative_identity(v: Option<i32>) -> bool {
1002 apply::<RcFnBrand, OptionBrand, _, _>(
1003 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
1004 v,
1005 ) == v
1006 }
1007
1008 #[quickcheck]
1010 fn applicative_homomorphism(x: i32) -> bool {
1011 let f = |x: i32| x.wrapping_mul(2);
1012 apply::<RcFnBrand, OptionBrand, _, _>(
1013 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
1014 pure::<OptionBrand, _>(x),
1015 ) == pure::<OptionBrand, _>(f(x))
1016 }
1017
1018 #[quickcheck]
1020 fn applicative_composition(
1021 w: Option<i32>,
1022 u_is_some: bool,
1023 v_is_some: bool,
1024 ) -> bool {
1025 let v_fn = |x: i32| x.wrapping_mul(2);
1026 let u_fn = |x: i32| x.wrapping_add(1);
1027
1028 let v = if v_is_some {
1029 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn))
1030 } else {
1031 None
1032 };
1033 let u = if u_is_some {
1034 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn))
1035 } else {
1036 None
1037 };
1038
1039 let vw = apply::<RcFnBrand, OptionBrand, _, _>(v.clone(), w);
1041 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), vw);
1042
1043 let uv = match (u, v) {
1046 (Some(uf), Some(vf)) => {
1047 let composed = move |x| uf(vf(x));
1048 Some(<RcFnBrand as CloneableFn>::new(composed))
1049 }
1050 _ => None,
1051 };
1052
1053 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(uv, w);
1054
1055 lhs == rhs
1056 }
1057
1058 #[quickcheck]
1060 fn applicative_interchange(y: i32) -> bool {
1061 let f = |x: i32| x.wrapping_mul(2);
1063 let u = pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f));
1064
1065 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), pure::<OptionBrand, _>(y));
1066
1067 let rhs_fn =
1068 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1069 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(pure::<OptionBrand, _>(rhs_fn), u);
1070
1071 lhs == rhs
1072 }
1073
1074 #[quickcheck]
1078 fn monad_left_identity(a: i32) -> bool {
1079 let f = |x: i32| Some(x.wrapping_mul(2));
1080 bind::<OptionBrand, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
1081 }
1082
1083 #[quickcheck]
1085 fn monad_right_identity(m: Option<i32>) -> bool {
1086 bind::<OptionBrand, _, _>(m, pure::<OptionBrand, _>) == m
1087 }
1088
1089 #[quickcheck]
1091 fn monad_associativity(m: Option<i32>) -> bool {
1092 let f = |x: i32| Some(x.wrapping_mul(2));
1093 let g = |x: i32| Some(x.wrapping_add(1));
1094 bind::<OptionBrand, _, _>(bind::<OptionBrand, _, _>(m, f), g)
1095 == bind::<OptionBrand, _, _>(m, |x| bind::<OptionBrand, _, _>(f(x), g))
1096 }
1097
1098 #[test]
1102 fn map_none() {
1103 assert_eq!(map::<OptionBrand, _, _>(|x: i32| x + 1, None), None);
1104 }
1105
1106 #[test]
1108 fn bind_none() {
1109 assert_eq!(bind::<OptionBrand, _, _>(None, |x: i32| Some(x + 1)), None);
1110 }
1111
1112 #[test]
1114 fn bind_returning_none() {
1115 assert_eq!(bind::<OptionBrand, _, _>(Some(5), |_| None::<i32>), None);
1116 }
1117
1118 #[test]
1120 fn fold_right_none() {
1121 assert_eq!(
1122 crate::classes::foldable::fold_right::<RcFnBrand, OptionBrand, _, _>(
1123 |x: i32, acc| x + acc,
1124 0,
1125 None
1126 ),
1127 0
1128 );
1129 }
1130
1131 #[test]
1133 fn fold_left_none() {
1134 assert_eq!(
1135 crate::classes::foldable::fold_left::<RcFnBrand, OptionBrand, _, _>(
1136 |acc, x: i32| acc + x,
1137 0,
1138 None
1139 ),
1140 0
1141 );
1142 }
1143
1144 #[test]
1146 fn traverse_none() {
1147 assert_eq!(
1148 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
1149 |x: i32| Some(x + 1),
1150 None
1151 ),
1152 Some(None)
1153 );
1154 }
1155
1156 #[test]
1158 fn traverse_returning_none() {
1159 assert_eq!(
1160 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
1161 |_: i32| None::<i32>,
1162 Some(5)
1163 ),
1164 None
1165 );
1166 }
1167}