1#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::{
9 Apply,
10 brands::Tuple1Brand,
11 classes::{
12 Applicative,
13 ApplyFirst,
14 ApplySecond,
15 CloneableFn,
16 Foldable,
17 Functor,
18 Lift,
19 MonadRec,
20 Monoid,
21 Pointed,
22 Semiapplicative,
23 Semimonad,
24 Traversable,
25 },
26 impl_kind,
27 kinds::*,
28 },
29 core::ops::ControlFlow,
30 fp_macros::*,
31 };
32
33 impl_kind! {
34 for Tuple1Brand {
35 type Of<A> = (A,);
36 }
37 }
38
39 impl_kind! {
40 for Tuple1Brand {
41 type Of<'a, A: 'a>: 'a = (A,);
42 }
43 }
44
45 impl Functor for Tuple1Brand {
46 #[document_signature]
50 #[document_type_parameters(
52 "The lifetime of the value.",
53 "The type of the value inside the tuple.",
54 "The type of the result of applying the function."
55 )]
56 #[document_parameters("The function to apply.", "The tuple to map over.")]
58 #[document_returns("A new 1-tuple containing the result of applying the function.")]
60 #[document_examples]
62 fn map<'a, A: 'a, B: 'a>(
74 func: impl Fn(A) -> B + 'a,
75 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
76 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
77 (func(fa.0),)
78 }
79 }
80
81 impl Lift for Tuple1Brand {
82 #[document_signature]
86 #[document_type_parameters(
88 "The lifetime of the values.",
89 "The type of the first tuple's value.",
90 "The type of the second tuple's value.",
91 "The return type of the function."
92 )]
93 #[document_parameters(
95 "The binary function to apply.",
96 "The first tuple.",
97 "The second tuple."
98 )]
99 #[document_returns("A new 1-tuple containing the result of applying the function.")]
101 #[document_examples]
102 fn lift2<'a, A, B, C>(
115 func: impl Fn(A, B) -> C + 'a,
116 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
117 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
118 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
119 where
120 A: 'a,
121 B: 'a,
122 C: 'a, {
123 (func(fa.0, fb.0),)
124 }
125 }
126
127 impl Pointed for Tuple1Brand {
128 #[document_signature]
132 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
134 #[document_parameters("The value to wrap.")]
136 #[document_returns("A 1-tuple containing the value.")]
138 #[document_examples]
140 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
151 (a,)
152 }
153 }
154
155 impl ApplyFirst for Tuple1Brand {}
156 impl ApplySecond for Tuple1Brand {}
157
158 impl Semiapplicative for Tuple1Brand {
159 #[document_signature]
163 #[document_type_parameters(
165 "The lifetime of the values.",
166 "The brand of the cloneable function wrapper.",
167 "The type of the input value.",
168 "The type of the output value."
169 )]
170 #[document_parameters(
172 "The tuple containing the function.",
173 "The tuple containing the value."
174 )]
175 #[document_returns("A new 1-tuple containing the result of applying the function.")]
177 #[document_examples]
178 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
191 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
192 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
193 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
194 (ff.0(fa.0),)
195 }
196 }
197
198 impl Semimonad for Tuple1Brand {
199 #[document_signature]
203 #[document_type_parameters(
205 "The lifetime of the values.",
206 "The type of the result of the first computation.",
207 "The type of the result of the second computation."
208 )]
209 #[document_parameters(
211 "The first tuple.",
212 "The function to apply to the value inside the tuple."
213 )]
214 #[document_returns("The result of applying `f` to the value.")]
216 #[document_examples]
217 fn bind<'a, A: 'a, B: 'a>(
229 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
230 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
231 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
232 func(ma.0)
233 }
234 }
235
236 impl Foldable for Tuple1Brand {
237 #[document_signature]
241 #[document_type_parameters(
243 "The lifetime of the values.",
244 "The brand of the cloneable function to use.",
245 "The type of the elements in the structure.",
246 "The type of the accumulator."
247 )]
248 #[document_parameters(
250 "The function to apply to each element and the accumulator.",
251 "The initial value of the accumulator.",
252 "The tuple to fold."
253 )]
254 #[document_returns("The final accumulator value.")]
256 #[document_examples]
257 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
269 func: impl Fn(A, B) -> B + 'a,
270 initial: B,
271 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
272 ) -> B
273 where
274 FnBrand: CloneableFn + 'a, {
275 func(fa.0, initial)
276 }
277
278 #[document_signature]
282 #[document_type_parameters(
284 "The lifetime of the values.",
285 "The brand of the cloneable function to use.",
286 "The type of the elements in the structure.",
287 "The type of the accumulator."
288 )]
289 #[document_parameters(
291 "The function to apply to the accumulator and each element.",
292 "The initial value of the accumulator.",
293 "The tuple to fold."
294 )]
295 #[document_returns("The final accumulator value.")]
297 #[document_examples]
298 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
310 func: impl Fn(B, A) -> B + 'a,
311 initial: B,
312 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
313 ) -> B
314 where
315 FnBrand: CloneableFn + 'a, {
316 func(initial, fa.0)
317 }
318
319 #[document_signature]
323 #[document_type_parameters(
325 "The lifetime of the values.",
326 "The brand of the cloneable function to use.",
327 "The type of the elements in the structure.",
328 "The type of the monoid."
329 )]
330 #[document_parameters(
332 "The thread-safe function to map each element to a monoid.",
333 "The tuple to fold."
334 )]
335 #[document_returns("The monoid value.")]
337 #[document_examples]
338 fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
350 func: impl Fn(A) -> M + 'a,
351 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
352 ) -> M
353 where
354 M: Monoid + 'a,
355 FnBrand: CloneableFn + 'a, {
356 func(fa.0)
357 }
358 }
359
360 impl Traversable for Tuple1Brand {
361 #[document_signature]
365 #[document_type_parameters(
367 "The lifetime of the values.",
368 "The type of the elements in the traversable structure.",
369 "The type of the elements in the resulting traversable structure.",
370 "The applicative context."
371 )]
372 #[document_parameters(
374 "The function to apply to each element, returning a value in an applicative context.",
375 "The tuple to traverse."
376 )]
377 #[document_returns("The 1-tuple wrapped in the applicative context.")]
379 #[document_examples]
380 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
392 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
393 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
394 ) -> 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>)>)
395 where
396 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
397 F::map(|b| (b,), func(ta.0))
398 }
399
400 #[document_signature]
404 #[document_type_parameters(
406 "The lifetime of the values.",
407 "The type of the elements in the traversable structure.",
408 "The applicative context."
409 )]
410 #[document_parameters("The tuple containing the applicative value.")]
412 #[document_returns("The 1-tuple wrapped in the applicative context.")]
414 #[document_examples]
416 fn sequence<'a, A: 'a + Clone, F: Applicative>(
428 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>)>)
429 ) -> 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>)>)
430 where
431 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
432 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
433 F::map(|a| (a,), ta.0)
434 }
435 }
436
437 impl MonadRec for Tuple1Brand {
438 #[document_signature]
443 #[document_type_parameters(
445 "The lifetime of the computation.",
446 "The type of the initial value and loop state.",
447 "The type of the result."
448 )]
449 #[document_parameters("The step function.", "The initial value.")]
451 #[document_returns("A 1-tuple containing the result of the computation.")]
453 #[document_examples]
455 fn tail_rec_m<'a, A: 'a, B: 'a>(
475 func: impl Fn(
476 A,
477 )
478 -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
479 + 'a,
480 initial: A,
481 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
482 let mut current = initial;
483 loop {
484 match func(current).0 {
485 ControlFlow::Continue(next) => current = next,
486 ControlFlow::Break(b) => return (b,),
487 }
488 }
489 }
490 }
491}
492
493#[cfg(test)]
494mod tests {
495
496 use {
497 crate::{
498 brands::{
499 OptionBrand,
500 RcFnBrand,
501 Tuple1Brand,
502 },
503 classes::{
504 CloneableFn,
505 functor::map,
506 pointed::pure,
507 semiapplicative::apply,
508 semimonad::bind,
509 },
510 functions::{
511 compose,
512 identity,
513 },
514 },
515 quickcheck_macros::quickcheck,
516 };
517
518 #[quickcheck]
522 fn functor_identity(x: i32) -> bool {
523 let x = (x,);
524 map::<Tuple1Brand, _, _>(identity, x) == x
525 }
526
527 #[quickcheck]
529 fn functor_composition(x: i32) -> bool {
530 let x = (x,);
531 let f = |x: i32| x.wrapping_add(1);
532 let g = |x: i32| x.wrapping_mul(2);
533 map::<Tuple1Brand, _, _>(compose(f, g), x)
534 == map::<Tuple1Brand, _, _>(f, map::<Tuple1Brand, _, _>(g, x))
535 }
536
537 #[quickcheck]
541 fn applicative_identity(v: i32) -> bool {
542 let v = (v,);
543 apply::<RcFnBrand, Tuple1Brand, _, _>(
544 pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(identity)),
545 v,
546 ) == v
547 }
548
549 #[quickcheck]
551 fn applicative_homomorphism(x: i32) -> bool {
552 let f = |x: i32| x.wrapping_mul(2);
553 apply::<RcFnBrand, Tuple1Brand, _, _>(
554 pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(f)),
555 pure::<Tuple1Brand, _>(x),
556 ) == pure::<Tuple1Brand, _>(f(x))
557 }
558
559 #[quickcheck]
561 fn applicative_composition(
562 w: i32,
563 u_val: i32,
564 v_val: i32,
565 ) -> bool {
566 let w = (w,);
567 let v_fn = move |x: i32| x.wrapping_mul(v_val);
568 let u_fn = move |x: i32| x.wrapping_add(u_val);
569
570 let v = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
571 let u = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
572
573 let vw = apply::<RcFnBrand, Tuple1Brand, _, _>(v.clone(), w);
575 let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), vw);
576
577 let composed = move |x| u_fn(v_fn(x));
579 let uv = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(composed));
580
581 let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(uv, w);
582
583 lhs == rhs
584 }
585
586 #[quickcheck]
588 fn applicative_interchange(y: i32) -> bool {
589 let f = |x: i32| x.wrapping_mul(2);
591 let u = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(f));
592
593 let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), pure::<Tuple1Brand, _>(y));
594
595 let rhs_fn =
596 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
597 let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(pure::<Tuple1Brand, _>(rhs_fn), u);
598
599 lhs == rhs
600 }
601
602 #[quickcheck]
606 fn monad_left_identity(a: i32) -> bool {
607 let f = |x: i32| (x.wrapping_mul(2),);
608 bind::<Tuple1Brand, _, _>(pure::<Tuple1Brand, _>(a), f) == f(a)
609 }
610
611 #[quickcheck]
613 fn monad_right_identity(m: i32) -> bool {
614 let m = (m,);
615 bind::<Tuple1Brand, _, _>(m, pure::<Tuple1Brand, _>) == m
616 }
617
618 #[quickcheck]
620 fn monad_associativity(m: i32) -> bool {
621 let m = (m,);
622 let f = |x: i32| (x.wrapping_mul(2),);
623 let g = |x: i32| (x.wrapping_add(1),);
624 bind::<Tuple1Brand, _, _>(bind::<Tuple1Brand, _, _>(m, f), g)
625 == bind::<Tuple1Brand, _, _>(m, |x| bind::<Tuple1Brand, _, _>(f(x), g))
626 }
627
628 #[test]
632 fn map_test() {
633 assert_eq!(map::<Tuple1Brand, _, _>(|x: i32| x + 1, (1,)), (2,));
634 }
635
636 #[test]
638 fn bind_test() {
639 assert_eq!(bind::<Tuple1Brand, _, _>((1,), |x| (x + 1,)), (2,));
640 }
641
642 #[test]
644 fn fold_right_test() {
645 assert_eq!(
646 crate::classes::foldable::fold_right::<RcFnBrand, Tuple1Brand, _, _>(
647 |x: i32, acc| x + acc,
648 0,
649 (1,)
650 ),
651 1
652 );
653 }
654
655 #[test]
657 fn fold_left_test() {
658 assert_eq!(
659 crate::classes::foldable::fold_left::<RcFnBrand, Tuple1Brand, _, _>(
660 |acc, x: i32| acc + x,
661 0,
662 (1,)
663 ),
664 1
665 );
666 }
667
668 #[test]
670 fn traverse_test() {
671 assert_eq!(
672 crate::classes::traversable::traverse::<Tuple1Brand, _, _, OptionBrand>(
673 |x: i32| Some(x + 1),
674 (1,)
675 ),
676 Some((2,))
677 );
678 }
679
680 #[quickcheck]
684 fn monad_rec_identity(x: i32) -> bool {
685 use {
686 crate::classes::monad_rec::tail_rec_m,
687 core::ops::ControlFlow,
688 };
689 tail_rec_m::<Tuple1Brand, _, _>(|a| (ControlFlow::Break(a),), x) == (x,)
690 }
691
692 #[test]
694 fn monad_rec_sum_range() {
695 use {
696 crate::classes::monad_rec::tail_rec_m,
697 core::ops::ControlFlow,
698 };
699 let result = tail_rec_m::<Tuple1Brand, _, _>(
700 |(n, acc)| {
701 if n == 0 {
702 (ControlFlow::Break(acc),)
703 } else {
704 (ControlFlow::Continue((n - 1, acc + n)),)
705 }
706 },
707 (100i64, 0i64),
708 );
709 assert_eq!(result, (5050,));
710 }
711
712 #[test]
714 fn monad_rec_stack_safety() {
715 use {
716 crate::classes::monad_rec::tail_rec_m,
717 core::ops::ControlFlow,
718 };
719 let iterations: i64 = 200_000;
720 let result = tail_rec_m::<Tuple1Brand, _, _>(
721 |acc| {
722 if acc < iterations {
723 (ControlFlow::Continue(acc + 1),)
724 } else {
725 (ControlFlow::Break(acc),)
726 }
727 },
728 0i64,
729 );
730 assert_eq!(result, (iterations,));
731 }
732}