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 Monoid,
20 Pointed,
21 Semiapplicative,
22 Semimonad,
23 Traversable,
24 },
25 impl_kind,
26 kinds::*,
27 },
28 fp_macros::*,
29 };
30
31 impl_kind! {
32 for Tuple1Brand {
33 type Of<A> = (A,);
34 }
35 }
36
37 impl_kind! {
38 for Tuple1Brand {
39 type Of<'a, A: 'a>: 'a = (A,);
40 }
41 }
42
43 impl Functor for Tuple1Brand {
44 #[document_signature]
48 #[document_type_parameters(
50 "The lifetime of the value.",
51 "The type of the value inside the tuple.",
52 "The type of the result of applying the function."
53 )]
54 #[document_parameters("The function to apply.", "The tuple to map over.")]
56 #[document_returns("A new 1-tuple containing the result of applying the function.")]
58 #[document_examples]
60 fn map<'a, A: 'a, B: 'a>(
72 func: impl Fn(A) -> B + 'a,
73 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
74 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
75 (func(fa.0),)
76 }
77 }
78
79 impl Lift for Tuple1Brand {
80 #[document_signature]
84 #[document_type_parameters(
86 "The lifetime of the values.",
87 "The type of the first tuple's value.",
88 "The type of the second tuple's value.",
89 "The return type of the function."
90 )]
91 #[document_parameters(
93 "The binary function to apply.",
94 "The first tuple.",
95 "The second tuple."
96 )]
97 #[document_returns("A new 1-tuple containing the result of applying the function.")]
99 #[document_examples]
100 fn lift2<'a, A, B, C>(
113 func: impl Fn(A, B) -> C + 'a,
114 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
115 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
116 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
117 where
118 A: 'a,
119 B: 'a,
120 C: 'a, {
121 (func(fa.0, fb.0),)
122 }
123 }
124
125 impl Pointed for Tuple1Brand {
126 #[document_signature]
130 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
132 #[document_parameters("The value to wrap.")]
134 #[document_returns("A 1-tuple containing the value.")]
136 #[document_examples]
138 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
149 (a,)
150 }
151 }
152
153 impl ApplyFirst for Tuple1Brand {}
154 impl ApplySecond for Tuple1Brand {}
155
156 impl Semiapplicative for Tuple1Brand {
157 #[document_signature]
161 #[document_type_parameters(
163 "The lifetime of the values.",
164 "The brand of the cloneable function wrapper.",
165 "The type of the input value.",
166 "The type of the output value."
167 )]
168 #[document_parameters(
170 "The tuple containing the function.",
171 "The tuple containing the value."
172 )]
173 #[document_returns("A new 1-tuple containing the result of applying the function.")]
175 #[document_examples]
176 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
189 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
190 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
191 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
192 (ff.0(fa.0),)
193 }
194 }
195
196 impl Semimonad for Tuple1Brand {
197 #[document_signature]
201 #[document_type_parameters(
203 "The lifetime of the values.",
204 "The type of the result of the first computation.",
205 "The type of the result of the second computation."
206 )]
207 #[document_parameters(
209 "The first tuple.",
210 "The function to apply to the value inside the tuple."
211 )]
212 #[document_returns("The result of applying `f` to the value.")]
214 #[document_examples]
215 fn bind<'a, A: 'a, B: 'a>(
227 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
228 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
229 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
230 func(ma.0)
231 }
232 }
233
234 impl Foldable for Tuple1Brand {
235 #[document_signature]
239 #[document_type_parameters(
241 "The lifetime of the values.",
242 "The brand of the cloneable function to use.",
243 "The type of the elements in the structure.",
244 "The type of the accumulator."
245 )]
246 #[document_parameters(
248 "The function to apply to each element and the accumulator.",
249 "The initial value of the accumulator.",
250 "The tuple to fold."
251 )]
252 #[document_returns("The final accumulator value.")]
254 #[document_examples]
255 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
267 func: impl Fn(A, B) -> B + 'a,
268 initial: B,
269 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
270 ) -> B
271 where
272 FnBrand: CloneableFn + 'a, {
273 func(fa.0, initial)
274 }
275
276 #[document_signature]
280 #[document_type_parameters(
282 "The lifetime of the values.",
283 "The brand of the cloneable function to use.",
284 "The type of the elements in the structure.",
285 "The type of the accumulator."
286 )]
287 #[document_parameters(
289 "The function to apply to the accumulator and each element.",
290 "The initial value of the accumulator.",
291 "The tuple to fold."
292 )]
293 #[document_returns("The final accumulator value.")]
295 #[document_examples]
296 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
308 func: impl Fn(B, A) -> B + 'a,
309 initial: B,
310 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
311 ) -> B
312 where
313 FnBrand: CloneableFn + 'a, {
314 func(initial, fa.0)
315 }
316
317 #[document_signature]
321 #[document_type_parameters(
323 "The lifetime of the values.",
324 "The brand of the cloneable function to use.",
325 "The type of the elements in the structure.",
326 "The type of the monoid."
327 )]
328 #[document_parameters(
330 "The thread-safe function to map each element to a monoid.",
331 "The tuple to fold."
332 )]
333 #[document_returns("The monoid value.")]
335 #[document_examples]
336 fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
348 func: impl Fn(A) -> M + 'a,
349 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
350 ) -> M
351 where
352 M: Monoid + 'a,
353 FnBrand: CloneableFn + 'a, {
354 func(fa.0)
355 }
356 }
357
358 impl Traversable for Tuple1Brand {
359 #[document_signature]
363 #[document_type_parameters(
365 "The lifetime of the values.",
366 "The type of the elements in the traversable structure.",
367 "The type of the elements in the resulting traversable structure.",
368 "The applicative context."
369 )]
370 #[document_parameters(
372 "The function to apply to each element, returning a value in an applicative context.",
373 "The tuple to traverse."
374 )]
375 #[document_returns("The 1-tuple wrapped in the applicative context.")]
377 #[document_examples]
378 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
390 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
391 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
392 ) -> 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>)>)
393 where
394 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
395 F::map(|b| (b,), func(ta.0))
396 }
397
398 #[document_signature]
402 #[document_type_parameters(
404 "The lifetime of the values.",
405 "The type of the elements in the traversable structure.",
406 "The applicative context."
407 )]
408 #[document_parameters("The tuple containing the applicative value.")]
410 #[document_returns("The 1-tuple wrapped in the applicative context.")]
412 #[document_examples]
414 fn sequence<'a, A: 'a + Clone, F: Applicative>(
426 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>)>)
427 ) -> 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>)>)
428 where
429 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
430 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
431 F::map(|a| (a,), ta.0)
432 }
433 }
434}
435
436#[cfg(test)]
437mod tests {
438
439 use {
440 crate::{
441 brands::{
442 OptionBrand,
443 RcFnBrand,
444 Tuple1Brand,
445 },
446 classes::{
447 CloneableFn,
448 functor::map,
449 pointed::pure,
450 semiapplicative::apply,
451 semimonad::bind,
452 },
453 functions::{
454 compose,
455 identity,
456 },
457 },
458 quickcheck_macros::quickcheck,
459 };
460
461 #[quickcheck]
465 fn functor_identity(x: i32) -> bool {
466 let x = (x,);
467 map::<Tuple1Brand, _, _>(identity, x) == x
468 }
469
470 #[quickcheck]
472 fn functor_composition(x: i32) -> bool {
473 let x = (x,);
474 let f = |x: i32| x.wrapping_add(1);
475 let g = |x: i32| x.wrapping_mul(2);
476 map::<Tuple1Brand, _, _>(compose(f, g), x)
477 == map::<Tuple1Brand, _, _>(f, map::<Tuple1Brand, _, _>(g, x))
478 }
479
480 #[quickcheck]
484 fn applicative_identity(v: i32) -> bool {
485 let v = (v,);
486 apply::<RcFnBrand, Tuple1Brand, _, _>(
487 pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(identity)),
488 v,
489 ) == v
490 }
491
492 #[quickcheck]
494 fn applicative_homomorphism(x: i32) -> bool {
495 let f = |x: i32| x.wrapping_mul(2);
496 apply::<RcFnBrand, Tuple1Brand, _, _>(
497 pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(f)),
498 pure::<Tuple1Brand, _>(x),
499 ) == pure::<Tuple1Brand, _>(f(x))
500 }
501
502 #[quickcheck]
504 fn applicative_composition(
505 w: i32,
506 u_val: i32,
507 v_val: i32,
508 ) -> bool {
509 let w = (w,);
510 let v_fn = move |x: i32| x.wrapping_mul(v_val);
511 let u_fn = move |x: i32| x.wrapping_add(u_val);
512
513 let v = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
514 let u = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
515
516 let vw = apply::<RcFnBrand, Tuple1Brand, _, _>(v.clone(), w);
518 let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), vw);
519
520 let composed = move |x| u_fn(v_fn(x));
522 let uv = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(composed));
523
524 let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(uv, w);
525
526 lhs == rhs
527 }
528
529 #[quickcheck]
531 fn applicative_interchange(y: i32) -> bool {
532 let f = |x: i32| x.wrapping_mul(2);
534 let u = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(f));
535
536 let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), pure::<Tuple1Brand, _>(y));
537
538 let rhs_fn =
539 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
540 let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(pure::<Tuple1Brand, _>(rhs_fn), u);
541
542 lhs == rhs
543 }
544
545 #[quickcheck]
549 fn monad_left_identity(a: i32) -> bool {
550 let f = |x: i32| (x.wrapping_mul(2),);
551 bind::<Tuple1Brand, _, _>(pure::<Tuple1Brand, _>(a), f) == f(a)
552 }
553
554 #[quickcheck]
556 fn monad_right_identity(m: i32) -> bool {
557 let m = (m,);
558 bind::<Tuple1Brand, _, _>(m, pure::<Tuple1Brand, _>) == m
559 }
560
561 #[quickcheck]
563 fn monad_associativity(m: i32) -> bool {
564 let m = (m,);
565 let f = |x: i32| (x.wrapping_mul(2),);
566 let g = |x: i32| (x.wrapping_add(1),);
567 bind::<Tuple1Brand, _, _>(bind::<Tuple1Brand, _, _>(m, f), g)
568 == bind::<Tuple1Brand, _, _>(m, |x| bind::<Tuple1Brand, _, _>(f(x), g))
569 }
570
571 #[test]
575 fn map_test() {
576 assert_eq!(map::<Tuple1Brand, _, _>(|x: i32| x + 1, (1,)), (2,));
577 }
578
579 #[test]
581 fn bind_test() {
582 assert_eq!(bind::<Tuple1Brand, _, _>((1,), |x| (x + 1,)), (2,));
583 }
584
585 #[test]
587 fn fold_right_test() {
588 assert_eq!(
589 crate::classes::foldable::fold_right::<RcFnBrand, Tuple1Brand, _, _>(
590 |x: i32, acc| x + acc,
591 0,
592 (1,)
593 ),
594 1
595 );
596 }
597
598 #[test]
600 fn fold_left_test() {
601 assert_eq!(
602 crate::classes::foldable::fold_left::<RcFnBrand, Tuple1Brand, _, _>(
603 |acc, x: i32| acc + x,
604 0,
605 (1,)
606 ),
607 1
608 );
609 }
610
611 #[test]
613 fn traverse_test() {
614 assert_eq!(
615 crate::classes::traversable::traverse::<Tuple1Brand, _, _, OptionBrand>(
616 |x: i32| Some(x + 1),
617 (1,)
618 ),
619 Some((2,))
620 );
621 }
622}