fp_library/types/identity.rs
1//! Implementations for [`Identity`], a type that wraps a value.
2//!
3//! This module provides implementations of functional programming traits for the [`Identity`] type.
4
5use crate::{
6 Apply,
7 brands::IdentityBrand,
8 classes::{
9 applicative::Applicative, apply_first::ApplyFirst, apply_second::ApplySecond,
10 clonable_fn::ClonableFn, foldable::Foldable, functor::Functor, lift::Lift, monoid::Monoid,
11 par_foldable::ParFoldable, pointed::Pointed, semiapplicative::Semiapplicative,
12 semimonad::Semimonad, send_clonable_fn::SendClonableFn, traversable::Traversable,
13 },
14 impl_kind,
15 kinds::*,
16};
17
18/// Wraps a value.
19///
20/// The `Identity` type represents a trivial wrapper around a value. It is the simplest possible container.
21/// It is often used as a base case for higher-kinded types or when a container is required but no additional effect is needed.
22///
23/// ### Type Parameters
24///
25/// * `A`: The type of the wrapped value.
26///
27/// ### Fields
28///
29/// * `0`: The wrapped value.
30///
31/// ### Examples
32///
33/// ```
34/// use fp_library::types::Identity;
35///
36/// let x = Identity(5);
37/// assert_eq!(x.0, 5);
38/// ```
39#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
40pub struct Identity<A>(pub A);
41
42impl_kind! {
43 for IdentityBrand {
44 type Of<'a, A: 'a>: 'a = Identity<A>;
45 }
46}
47
48impl Functor for IdentityBrand {
49 /// Maps a function over the value in the identity.
50 ///
51 /// This method applies a function to the value inside the identity, producing a new identity with the transformed value.
52 ///
53 /// ### Type Signature
54 ///
55 /// `forall b a. Functor Identity => (a -> b, Identity a) -> Identity b`
56 ///
57 /// ### Type Parameters
58 ///
59 /// * `B`: The type of the result of applying the function.
60 /// * `A`: The type of the value inside the identity.
61 /// * `F`: The type of the function to apply.
62 ///
63 /// ### Parameters
64 ///
65 /// * `f`: The function to apply.
66 /// * `fa`: The identity to map over.
67 ///
68 /// ### Returns
69 ///
70 /// A new identity containing the result of applying the function.
71 ///
72 /// ### Examples
73 ///
74 /// ```
75 /// use fp_library::functions::*;
76 /// use fp_library::brands::IdentityBrand;
77 /// use fp_library::types::Identity;
78 ///
79 /// let x = Identity(5);
80 /// let y = map::<IdentityBrand, _, _, _>(|i| i * 2, x);
81 /// assert_eq!(y, Identity(10));
82 /// ```
83 fn map<'a, B: 'a, A: 'a, F>(
84 f: F,
85 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
86 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
87 where
88 F: Fn(A) -> B + 'a,
89 {
90 Identity(f(fa.0))
91 }
92}
93
94impl Lift for IdentityBrand {
95 /// Lifts a binary function into the identity context.
96 ///
97 /// This method lifts a binary function to operate on values within the identity context.
98 ///
99 /// ### Type Signature
100 ///
101 /// `forall c a b. Lift Identity => ((a, b) -> c, Identity a, Identity b) -> Identity c`
102 ///
103 /// ### Type Parameters
104 ///
105 /// * `C`: The return type of the function.
106 /// * `A`: The type of the first identity's value.
107 /// * `B`: The type of the second identity's value.
108 /// * `F`: The type of the binary function.
109 ///
110 /// ### Parameters
111 ///
112 /// * `f`: The binary function to apply.
113 /// * `fa`: The first identity.
114 /// * `fb`: The second identity.
115 ///
116 /// ### Returns
117 ///
118 /// A new identity containing the result of applying the function.
119 ///
120 /// ### Examples
121 ///
122 /// ```
123 /// use fp_library::functions::*;
124 /// use fp_library::brands::IdentityBrand;
125 /// use fp_library::types::Identity;
126 ///
127 /// let x = Identity(1);
128 /// let y = Identity(2);
129 /// let z = lift2::<IdentityBrand, _, _, _, _>(|a, b| a + b, x, y);
130 /// assert_eq!(z, Identity(3));
131 /// ```
132 fn lift2<'a, C, A, B, F>(
133 f: F,
134 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
135 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
136 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
137 where
138 F: Fn(A, B) -> C + 'a,
139 A: 'a,
140 B: 'a,
141 C: 'a,
142 {
143 Identity(f(fa.0, fb.0))
144 }
145}
146
147impl Pointed for IdentityBrand {
148 /// Wraps a value in an identity.
149 ///
150 /// This method wraps a value in an identity context.
151 ///
152 /// ### Type Signature
153 ///
154 /// `forall a. Pointed Identity => a -> Identity a`
155 ///
156 /// ### Type Parameters
157 ///
158 /// * `A`: The type of the value to wrap.
159 ///
160 /// ### Parameters
161 ///
162 /// * `a`: The value to wrap.
163 ///
164 /// ### Returns
165 ///
166 /// An identity containing the value.
167 ///
168 /// ### Examples
169 ///
170 /// ```
171 /// use fp_library::functions::*;
172 /// use fp_library::brands::IdentityBrand;
173 /// use fp_library::types::Identity;
174 ///
175 /// let x = pure::<IdentityBrand, _>(5);
176 /// assert_eq!(x, Identity(5));
177 /// ```
178 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
179 Identity(a)
180 }
181}
182
183impl ApplyFirst for IdentityBrand {}
184impl ApplySecond for IdentityBrand {}
185
186impl Semiapplicative for IdentityBrand {
187 /// Applies a wrapped function to a wrapped value.
188 ///
189 /// This method applies a function wrapped in an identity to a value wrapped in an identity.
190 ///
191 /// ### Type Signature
192 ///
193 /// `forall fn_brand b a. Semiapplicative Identity => (Identity (fn_brand a b), Identity a) -> Identity b`
194 ///
195 /// ### Type Parameters
196 ///
197 /// * `FnBrand`: The brand of the clonable function wrapper.
198 /// * `B`: The type of the output value.
199 /// * `A`: The type of the input value.
200 ///
201 /// ### Parameters
202 ///
203 /// * `ff`: The identity containing the function.
204 /// * `fa`: The identity containing the value.
205 ///
206 /// ### Returns
207 ///
208 /// A new identity containing the result of applying the function.
209 ///
210 /// ### Examples
211 ///
212 /// ```
213 /// use fp_library::{brands::*, classes::*, functions::*, types::*};
214 ///
215 /// let f = Identity(clonable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
216 /// let x = Identity(5);
217 /// let y = apply::<RcFnBrand, IdentityBrand, _, _>(f, x);
218 /// assert_eq!(y, Identity(10));
219 /// ```
220 fn apply<'a, FnBrand: 'a + ClonableFn, B: 'a, A: 'a + Clone>(
221 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as ClonableFn>::Of<'a, A, B>>),
222 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
223 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
224 Identity(ff.0(fa.0))
225 }
226}
227
228impl Semimonad for IdentityBrand {
229 /// Chains identity computations.
230 ///
231 /// This method chains two identity computations, where the second computation depends on the result of the first.
232 ///
233 /// ### Type Signature
234 ///
235 /// `forall b a. Semimonad Identity => (Identity a, a -> Identity b) -> Identity b`
236 ///
237 /// ### Type Parameters
238 ///
239 /// * `B`: The type of the result of the second computation.
240 /// * `A`: The type of the result of the first computation.
241 /// * `F`: The type of the function to apply.
242 ///
243 /// ### Parameters
244 ///
245 /// * `ma`: The first identity.
246 /// * `f`: The function to apply to the value inside the identity.
247 ///
248 /// ### Returns
249 ///
250 /// The result of applying `f` to the value.
251 ///
252 /// ### Examples
253 ///
254 /// ```
255 /// use fp_library::functions::*;
256 /// use fp_library::brands::IdentityBrand;
257 /// use fp_library::types::Identity;
258 ///
259 /// let x = Identity(5);
260 /// let y = bind::<IdentityBrand, _, _, _>(x, |i| Identity(i * 2));
261 /// assert_eq!(y, Identity(10));
262 /// ```
263 fn bind<'a, B: 'a, A: 'a, F>(
264 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
265 f: F,
266 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
267 where
268 F: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
269 {
270 f(ma.0)
271 }
272}
273
274impl Foldable for IdentityBrand {
275 /// Folds the identity from the right.
276 ///
277 /// This method performs a right-associative fold of the identity. Since `Identity` contains only one element, this is equivalent to applying the function to the element and the initial value.
278 ///
279 /// ### Type Signature
280 ///
281 /// `forall b a. Foldable Identity => ((a, b) -> b, b, Identity a) -> b`
282 ///
283 /// ### Type Parameters
284 ///
285 /// * `FnBrand`: The brand of the clonable function to use.
286 /// * `B`: The type of the accumulator.
287 /// * `A`: The type of the elements in the structure.
288 /// * `Func`: The type of the folding function.
289 ///
290 /// ### Parameters
291 ///
292 /// * `func`: The function to apply to each element and the accumulator.
293 /// * `initial`: The initial value of the accumulator.
294 /// * `fa`: The identity to fold.
295 ///
296 /// ### Returns
297 ///
298 /// The final accumulator value.
299 ///
300 /// ### Examples
301 ///
302 /// ```
303 /// use fp_library::functions::*;
304 /// use fp_library::brands::{IdentityBrand, RcFnBrand};
305 /// use fp_library::types::Identity;
306 ///
307 /// let x = Identity(5);
308 /// let y = fold_right::<RcFnBrand, IdentityBrand, _, _, _>(|a, b| a + b, 10, x);
309 /// assert_eq!(y, 15);
310 /// ```
311 fn fold_right<'a, FnBrand, B: 'a, A: 'a, Func>(
312 func: Func,
313 initial: B,
314 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
315 ) -> B
316 where
317 Func: Fn(A, B) -> B + 'a,
318 FnBrand: ClonableFn + 'a,
319 {
320 func(fa.0, initial)
321 }
322
323 /// Folds the identity from the left.
324 ///
325 /// This method performs a left-associative fold of the identity. Since `Identity` contains only one element, this is equivalent to applying the function to the initial value and the element.
326 ///
327 /// ### Type Signature
328 ///
329 /// `forall b a. Foldable Identity => ((b, a) -> b, b, Identity a) -> b`
330 ///
331 /// ### Type Parameters
332 ///
333 /// * `FnBrand`: The brand of the clonable function to use.
334 /// * `B`: The type of the accumulator.
335 /// * `A`: The type of the elements in the structure.
336 /// * `Func`: The type of the folding function.
337 ///
338 /// ### Parameters
339 ///
340 /// * `func`: The function to apply to the accumulator and each element.
341 /// * `initial`: The initial value of the accumulator.
342 /// * `fa`: The structure to fold.
343 ///
344 /// ### Returns
345 ///
346 /// The final accumulator value.
347 ///
348 /// ### Examples
349 ///
350 /// ```
351 /// use fp_library::functions::*;
352 /// use fp_library::brands::{IdentityBrand, RcFnBrand};
353 /// use fp_library::types::Identity;
354 ///
355 /// let x = Identity(5);
356 /// let y = fold_left::<RcFnBrand, IdentityBrand, _, _, _>(|b, a| b + a, 10, x);
357 /// assert_eq!(y, 15);
358 /// ```
359 fn fold_left<'a, FnBrand, B: 'a, A: 'a, Func>(
360 func: Func,
361 initial: B,
362 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
363 ) -> B
364 where
365 Func: Fn(B, A) -> B + 'a,
366 FnBrand: ClonableFn + 'a,
367 {
368 func(initial, fa.0)
369 }
370
371 /// Maps the value to a monoid and returns it.
372 ///
373 /// This method maps the element of the identity to a monoid.
374 ///
375 /// ### Type Signature
376 ///
377 /// `forall m a. (Foldable Identity, Monoid m) => ((a) -> m, Identity a) -> m`
378 ///
379 /// ### Type Parameters
380 ///
381 /// * `FnBrand`: The brand of the clonable function to use.
382 /// * `M`: The type of the monoid.
383 /// * `A`: The type of the elements in the structure.
384 /// * `Func`: The type of the mapping function.
385 ///
386 /// ### Parameters
387 ///
388 /// * `func`: The mapping function.
389 /// * `fa`: The identity to fold.
390 ///
391 /// ### Returns
392 ///
393 /// The monoid value.
394 ///
395 /// ### Examples
396 ///
397 /// ```
398 /// use fp_library::functions::*;
399 /// use fp_library::brands::{IdentityBrand, RcFnBrand};
400 /// use fp_library::types::{Identity, string}; // Import to bring Monoid impl for String into scope
401 ///
402 /// let x = Identity(5);
403 /// let y = fold_map::<RcFnBrand, IdentityBrand, _, _, _>(|a: i32| a.to_string(), x);
404 /// assert_eq!(y, "5".to_string());
405 /// ```
406 fn fold_map<'a, FnBrand, M, A: 'a, Func>(
407 func: Func,
408 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
409 ) -> M
410 where
411 M: Monoid + 'a,
412 Func: Fn(A) -> M + 'a,
413 FnBrand: ClonableFn + 'a,
414 {
415 func(fa.0)
416 }
417}
418
419impl Traversable for IdentityBrand {
420 /// Traverses the identity with an applicative function.
421 ///
422 /// This method maps the element of the identity to a computation, evaluates it, and wraps the result in the applicative context.
423 ///
424 /// ### Type Signature
425 ///
426 /// `forall f b a. (Traversable Identity, Applicative f) => (a -> f b, Identity a) -> f (Identity b)`
427 ///
428 /// ### Type Parameters
429 ///
430 /// * `F`: The applicative context.
431 /// * `B`: The type of the elements in the resulting traversable structure.
432 /// * `A`: The type of the elements in the traversable structure.
433 /// * `Func`: The type of the function to apply.
434 ///
435 /// ### Parameters
436 ///
437 /// * `func`: The function to apply to each element, returning a value in an applicative context.
438 /// * `ta`: The identity to traverse.
439 ///
440 /// ### Returns
441 ///
442 /// The identity wrapped in the applicative context.
443 ///
444 /// ### Examples
445 ///
446 /// ```
447 /// use fp_library::functions::*;
448 /// use fp_library::brands::{IdentityBrand, OptionBrand};
449 /// use fp_library::types::Identity;
450 ///
451 /// let x = Identity(5);
452 /// let y = traverse::<IdentityBrand, OptionBrand, _, _, _>(|a| Some(a * 2), x);
453 /// assert_eq!(y, Some(Identity(10)));
454 /// ```
455 fn traverse<'a, F: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
456 func: Func,
457 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
458 ) -> 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>)>)
459 where
460 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
461 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
462 {
463 F::map(|b| Identity(b), func(ta.0))
464 }
465 /// Sequences an identity of applicative.
466 ///
467 /// This method evaluates the computation inside the identity and wraps the result in the applicative context.
468 ///
469 /// ### Type Signature
470 ///
471 /// `forall f a. (Traversable Identity, Applicative f) => (Identity (f a)) -> f (Identity a)`
472 ///
473 /// ### Type Parameters
474 ///
475 /// * `F`: The applicative context.
476 /// * `A`: The type of the elements in the traversable structure.
477 ///
478 /// ### Parameters
479 ///
480 /// * `ta`: The identity containing the applicative value.
481 ///
482 /// # Returns
483 ///
484 /// The identity wrapped in the applicative context.
485 ///
486 /// ### Examples
487 ///
488 /// ```
489 /// use fp_library::functions::*;
490 /// use fp_library::brands::{IdentityBrand, OptionBrand};
491 /// use fp_library::types::Identity;
492 ///
493 /// let x = Identity(Some(5));
494 /// let y = sequence::<IdentityBrand, OptionBrand, _>(x);
495 /// assert_eq!(y, Some(Identity(5)));
496 /// ```
497 fn sequence<'a, F: Applicative, A: 'a + Clone>(
498 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>)>)
499 ) -> 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>)>)
500 where
501 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
502 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
503 {
504 F::map(|a| Identity(a), ta.0)
505 }
506}
507
508impl<FnBrand: SendClonableFn> ParFoldable<FnBrand> for IdentityBrand {
509 /// Maps the value to a monoid and returns it in parallel.
510 ///
511 /// This method maps the element of the identity to a monoid. Since `Identity` contains only one element, no actual parallelism occurs, but the interface is satisfied.
512 ///
513 /// ### Type Signature
514 ///
515 /// `forall fn_brand m a. (ParFoldable Identity, Monoid m, Send m, Sync m) => (fn_brand a m, Identity a) -> m`
516 ///
517 /// ### Type Parameters
518 ///
519 /// * `M`: The monoid type (must be `Send + Sync`).
520 /// * `A`: The element type (must be `Send + Sync`).
521 ///
522 /// ### Parameters
523 ///
524 /// * `func`: The mapping function.
525 /// * `fa`: The identity to fold.
526 ///
527 /// ### Returns
528 ///
529 /// The combined monoid value.
530 ///
531 /// ### Examples
532 ///
533 /// ```
534 /// use fp_library::functions::*;
535 /// use fp_library::brands::{IdentityBrand, ArcFnBrand};
536 /// use fp_library::types::Identity;
537 ///
538 /// let x = Identity(1);
539 /// let f = send_clonable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
540 /// let y = par_fold_map::<ArcFnBrand, IdentityBrand, _, _>(f, x);
541 /// assert_eq!(y, "1".to_string());
542 /// ```
543 fn par_fold_map<'a, M, A>(
544 func: <FnBrand as SendClonableFn>::SendOf<'a, A, M>,
545 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
546 ) -> M
547 where
548 A: 'a + Clone + Send + Sync,
549 M: Monoid + Send + Sync + 'a,
550 {
551 func(fa.0)
552 }
553
554 /// Folds the identity from the right in parallel.
555 ///
556 /// This method performs a right-associative fold of the identity. Since `Identity` contains only one element, no actual parallelism occurs.
557 ///
558 /// ### Type Signature
559 ///
560 /// `forall fn_brand b a. ParFoldable Identity => (fn_brand (a, b) b, b, Identity a) -> b`
561 ///
562 /// ### Type Parameters
563 ///
564 /// * `B`: The accumulator type (must be `Send + Sync`).
565 /// * `A`: The element type (must be `Send + Sync`).
566 ///
567 /// ### Parameters
568 ///
569 /// * `func`: The thread-safe function to apply to each element and the accumulator.
570 /// * `initial`: The initial value of the accumulator.
571 /// * `fa`: The identity to fold.
572 ///
573 /// ### Returns
574 ///
575 /// The final accumulator value.
576 ///
577 /// ### Examples
578 ///
579 /// ```
580 /// use fp_library::functions::*;
581 /// use fp_library::brands::{IdentityBrand, ArcFnBrand};
582 /// use fp_library::types::Identity;
583 ///
584 /// let x = Identity(1);
585 /// let f = send_clonable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
586 /// let y = par_fold_right::<ArcFnBrand, IdentityBrand, _, _>(f, 10, x);
587 /// assert_eq!(y, 11);
588 /// ```
589 fn par_fold_right<'a, B, A>(
590 func: <FnBrand as SendClonableFn>::SendOf<'a, (A, B), B>,
591 initial: B,
592 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
593 ) -> B
594 where
595 A: 'a + Clone + Send + Sync,
596 B: Send + Sync + 'a,
597 {
598 func((fa.0, initial))
599 }
600}
601
602#[cfg(test)]
603mod tests {
604 use super::*;
605 use crate::{
606 brands::{OptionBrand, RcFnBrand},
607 classes::{functor::map, pointed::pure, semiapplicative::apply, semimonad::bind},
608 functions::{compose, identity},
609 };
610 use quickcheck_macros::quickcheck;
611
612 // Functor Laws
613
614 /// Tests the identity law for Functor.
615 #[quickcheck]
616 fn functor_identity(x: i32) -> bool {
617 let x = Identity(x);
618 map::<IdentityBrand, _, _, _>(identity, x) == x
619 }
620
621 /// Tests the composition law for Functor.
622 #[quickcheck]
623 fn functor_composition(x: i32) -> bool {
624 let x = Identity(x);
625 let f = |x: i32| x.wrapping_add(1);
626 let g = |x: i32| x.wrapping_mul(2);
627 map::<IdentityBrand, _, _, _>(compose(f, g), x)
628 == map::<IdentityBrand, _, _, _>(f, map::<IdentityBrand, _, _, _>(g, x))
629 }
630
631 // Applicative Laws
632
633 /// Tests the identity law for Applicative.
634 #[quickcheck]
635 fn applicative_identity(v: i32) -> bool {
636 let v = Identity(v);
637 apply::<RcFnBrand, IdentityBrand, _, _>(
638 pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(identity)),
639 v,
640 ) == v
641 }
642
643 /// Tests the homomorphism law for Applicative.
644 #[quickcheck]
645 fn applicative_homomorphism(x: i32) -> bool {
646 let f = |x: i32| x.wrapping_mul(2);
647 apply::<RcFnBrand, IdentityBrand, _, _>(
648 pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(f)),
649 pure::<IdentityBrand, _>(x),
650 ) == pure::<IdentityBrand, _>(f(x))
651 }
652
653 /// Tests the composition law for Applicative.
654 #[quickcheck]
655 fn applicative_composition(
656 w: i32,
657 u_val: i32,
658 v_val: i32,
659 ) -> bool {
660 let w = Identity(w);
661 let v_fn = move |x: i32| x.wrapping_mul(v_val);
662 let u_fn = move |x: i32| x.wrapping_add(u_val);
663
664 let v = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(v_fn));
665 let u = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(u_fn));
666
667 // RHS: u <*> (v <*> w)
668 let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w.clone());
669 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
670
671 // LHS: pure(compose) <*> u <*> v <*> w
672 // equivalent to (u . v) <*> w
673 let composed = move |x| u_fn(v_fn(x));
674 let uv = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(composed));
675
676 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
677
678 lhs == rhs
679 }
680
681 /// Tests the interchange law for Applicative.
682 #[quickcheck]
683 fn applicative_interchange(y: i32) -> bool {
684 // u <*> pure y = pure ($ y) <*> u
685 let f = |x: i32| x.wrapping_mul(2);
686 let u = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(f));
687
688 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
689
690 let rhs_fn = <RcFnBrand as ClonableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
691 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
692
693 lhs == rhs
694 }
695
696 // Monad Laws
697
698 /// Tests the left identity law for Monad.
699 #[quickcheck]
700 fn monad_left_identity(a: i32) -> bool {
701 let f = |x: i32| Identity(x.wrapping_mul(2));
702 bind::<IdentityBrand, _, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
703 }
704
705 /// Tests the right identity law for Monad.
706 #[quickcheck]
707 fn monad_right_identity(m: i32) -> bool {
708 let m = Identity(m);
709 bind::<IdentityBrand, _, _, _>(m, pure::<IdentityBrand, _>) == m
710 }
711
712 /// Tests the associativity law for Monad.
713 #[quickcheck]
714 fn monad_associativity(m: i32) -> bool {
715 let m = Identity(m);
716 let f = |x: i32| Identity(x.wrapping_mul(2));
717 let g = |x: i32| Identity(x.wrapping_add(1));
718 bind::<IdentityBrand, _, _, _>(bind::<IdentityBrand, _, _, _>(m, f), g)
719 == bind::<IdentityBrand, _, _, _>(m, |x| bind::<IdentityBrand, _, _, _>(f(x), g))
720 }
721
722 // Edge Cases
723
724 /// Tests the `map` function.
725 #[test]
726 fn map_test() {
727 assert_eq!(map::<IdentityBrand, _, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
728 }
729
730 /// Tests the `bind` function.
731 #[test]
732 fn bind_test() {
733 assert_eq!(bind::<IdentityBrand, _, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
734 }
735
736 /// Tests the `fold_right` function.
737 #[test]
738 fn fold_right_test() {
739 assert_eq!(
740 crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _, _>(
741 |x: i32, acc| x + acc,
742 0,
743 Identity(1)
744 ),
745 1
746 );
747 }
748
749 /// Tests the `fold_left` function.
750 #[test]
751 fn fold_left_test() {
752 assert_eq!(
753 crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _, _>(
754 |acc, x: i32| acc + x,
755 0,
756 Identity(1)
757 ),
758 1
759 );
760 }
761
762 /// Tests the `traverse` function.
763 #[test]
764 fn traverse_test() {
765 assert_eq!(
766 crate::classes::traversable::traverse::<IdentityBrand, OptionBrand, _, _, _>(
767 |x: i32| Some(x + 1),
768 Identity(1)
769 ),
770 Some(Identity(2))
771 );
772 }
773
774 // ParFoldable Tests
775
776 /// Tests `par_fold_map`.
777 #[test]
778 fn par_fold_map_test() {
779 use crate::{brands::*, functions::*};
780
781 let x = Identity(1);
782 let f = send_clonable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
783 assert_eq!(par_fold_map::<ArcFnBrand, IdentityBrand, _, _>(f, x), "1".to_string());
784 }
785
786 /// Tests `par_fold_right`.
787 #[test]
788 fn par_fold_right_test() {
789 use crate::{brands::*, functions::*};
790
791 let x = Identity(1);
792 let f = send_clonable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
793 assert_eq!(par_fold_right::<ArcFnBrand, IdentityBrand, _, _>(f, 10, x), 11);
794 }
795}