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