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