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