fp_library/types/vec.rs
1//! Implementations for [`Vec`].
2//!
3//! This module provides implementations of various type classes for the `Vec` type.
4
5#[cfg(feature = "rayon")]
6use rayon::prelude::*;
7
8use crate::{
9 Apply,
10 brands::VecBrand,
11 classes::{
12 applicative::Applicative, apply_first::ApplyFirst, apply_second::ApplySecond,
13 clonable_fn::ClonableFn, foldable::Foldable, functor::Functor, lift::Lift, monoid::Monoid,
14 par_foldable::ParFoldable, pointed::Pointed, semiapplicative::Semiapplicative,
15 semigroup::Semigroup, semimonad::Semimonad, send_clonable_fn::SendClonableFn,
16 traversable::Traversable,
17 },
18 impl_kind,
19 kinds::*,
20};
21
22impl_kind! {
23 for VecBrand {
24 type Of<'a, A: 'a>: 'a = Vec<A>;
25 }
26}
27
28impl VecBrand {
29 /// Constructs a new vector by prepending a value to an existing vector.
30 ///
31 /// This method creates a new vector with the given head element followed by the elements of the tail vector.
32 ///
33 /// ### Type Signature
34 ///
35 /// `forall a. a -> Vec a -> Vec a`
36 ///
37 /// ### Type Parameters
38 ///
39 /// * `A`: The type of the elements in the vector.
40 ///
41 /// ### Parameters
42 ///
43 /// * `head`: A value to prepend to the vector.
44 /// * `tail`: A vector to prepend the value to.
45 ///
46 /// ### Returns
47 ///
48 /// A new vector consisting of the `head` element prepended to the `tail` vector.
49 ///
50 /// ### Examples
51 ///
52 /// ```
53 /// use fp_library::brands::VecBrand;
54 ///
55 /// let head = 1;
56 /// let tail = vec![2, 3];
57 /// let new_vec = VecBrand::construct(head, tail);
58 /// assert_eq!(new_vec, vec![1, 2, 3]);
59 ///
60 /// let empty_tail = vec![];
61 /// let single_element = VecBrand::construct(42, empty_tail);
62 /// assert_eq!(single_element, vec![42]);
63 /// ```
64 pub fn construct<A>(
65 head: A,
66 tail: Vec<A>,
67 ) -> Vec<A>
68 where
69 A: Clone,
70 {
71 [vec![head], tail].concat()
72 }
73
74 /// Deconstructs a slice into its head element and tail vector.
75 ///
76 /// This method splits a slice into its first element and the rest of the elements as a new vector.
77 ///
78 /// ### Type Signature
79 ///
80 /// `forall a. &[a] -> Option (a, Vec a)`
81 ///
82 /// ### Type Parameters
83 ///
84 /// * `A`: The type of the elements in the vector.
85 ///
86 /// ### Parameters
87 ///
88 /// * `slice`: The vector slice to deconstruct.
89 ///
90 /// ### Returns
91 ///
92 /// An [`Option`] containing a tuple of the head element and the remaining tail vector,
93 /// or [`None`] if the slice is empty.
94 ///
95 /// ### Examples
96 ///
97 /// ```
98 /// use fp_library::brands::VecBrand;
99 ///
100 /// let vec = vec![1, 2, 3];
101 /// let deconstructed = VecBrand::deconstruct(&vec);
102 /// assert_eq!(deconstructed, Some((1, vec![2, 3])));
103 ///
104 /// let empty: Vec<i32> = vec![];
105 /// assert_eq!(VecBrand::deconstruct(&empty), None);
106 /// ```
107 pub fn deconstruct<A>(slice: &[A]) -> Option<(A, Vec<A>)>
108 where
109 A: Clone,
110 {
111 match slice {
112 [] => None,
113 [head, tail @ ..] => Some((head.clone(), tail.to_vec())),
114 }
115 }
116}
117
118impl Functor for VecBrand {
119 /// Maps a function over the vector.
120 ///
121 /// This method applies a function to each element of the vector, producing a new vector with the transformed values.
122 ///
123 /// ### Type Signature
124 ///
125 /// `forall a b. Functor Vec => (a -> b, Vec a) -> Vec b`
126 ///
127 /// ### Type Parameters
128 ///
129 /// * `F`: The type of the function to apply.
130 /// * `A`: The type of the elements in the vector.
131 /// * `B`: The type of the elements in the resulting vector.
132 ///
133 /// ### Parameters
134 ///
135 /// * `f`: The function to apply to each element.
136 /// * `fa`: The vector to map over.
137 ///
138 /// ### Returns
139 ///
140 /// A new vector containing the results of applying the function.
141 ///
142 /// ### Examples
143 ///
144 /// ```
145 /// use fp_library::classes::functor::map;
146 /// use fp_library::brands::VecBrand;
147 ///
148 /// assert_eq!(map::<VecBrand, _, _, _>(|x: i32| x * 2, vec![1, 2, 3]), vec![2, 4, 6]);
149 /// ```
150 fn map<'a, F, A: 'a, B: 'a>(
151 f: F,
152 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
153 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
154 where
155 F: Fn(A) -> B + 'a,
156 {
157 fa.into_iter().map(f).collect()
158 }
159}
160
161impl Lift for VecBrand {
162 /// Lifts a binary function into the vector context (Cartesian product).
163 ///
164 /// This method applies a binary function to all pairs of elements from two vectors, producing a new vector containing the results (Cartesian product).
165 ///
166 /// ### Type Signature
167 ///
168 /// `forall a b c. Lift Vec => ((a, b) -> c, Vec a, Vec b) -> Vec c`
169 ///
170 /// ### Type Parameters
171 ///
172 /// * `F`: The type of the binary function.
173 /// * `A`: The type of the elements in the first vector.
174 /// * `B`: The type of the elements in the second vector.
175 /// * `C`: The type of the elements in the resulting vector.
176 ///
177 /// ### Parameters
178 ///
179 /// * `f`: The binary function to apply.
180 /// * `fa`: The first vector.
181 /// * `fb`: The second vector.
182 ///
183 /// ### Returns
184 ///
185 /// A new vector containing the results of applying the function to all pairs of elements.
186 ///
187 /// ### Examples
188 ///
189 /// ```
190 /// use fp_library::classes::lift::lift2;
191 /// use fp_library::brands::VecBrand;
192 ///
193 /// assert_eq!(
194 /// lift2::<VecBrand, _, _, _, _>(|x, y| x + y, vec![1, 2], vec![10, 20]),
195 /// vec![11, 21, 12, 22]
196 /// );
197 /// ```
198 fn lift2<'a, F, A, B, C>(
199 f: F,
200 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
201 fb: Apply!(brand: Self, signature: ('a, B: 'a) -> 'a),
202 ) -> Apply!(brand: Self, signature: ('a, C: 'a) -> 'a)
203 where
204 F: Fn(A, B) -> C + 'a,
205 A: Clone + 'a,
206 B: Clone + 'a,
207 C: 'a,
208 {
209 fa.iter().flat_map(|a| fb.iter().map(|b| f(a.clone(), b.clone()))).collect()
210 }
211}
212
213impl Pointed for VecBrand {
214 /// Wraps a value in a vector.
215 ///
216 /// This method creates a new vector containing the single given value.
217 ///
218 /// ### Type Signature
219 ///
220 /// `forall a. Pointed Vec => a -> Vec a`
221 ///
222 /// ### Type Parameters
223 ///
224 /// * `A`: The type of the value to wrap.
225 ///
226 /// ### Parameters
227 ///
228 /// * `a`: The value to wrap.
229 ///
230 /// ### Returns
231 ///
232 /// A vector containing the single value.
233 ///
234 /// ### Examples
235 ///
236 /// ```
237 /// use fp_library::classes::pointed::pure;
238 /// use fp_library::brands::VecBrand;
239 ///
240 /// assert_eq!(pure::<VecBrand, _>(5), vec![5]);
241 /// ```
242 fn pure<'a, A: 'a>(a: A) -> Apply!(brand: Self, signature: ('a, A: 'a) -> 'a) {
243 vec![a]
244 }
245}
246
247impl ApplyFirst for VecBrand {}
248impl ApplySecond for VecBrand {}
249
250impl Semiapplicative for VecBrand {
251 /// Applies wrapped functions to wrapped values (Cartesian product).
252 ///
253 /// This method applies each function in the first vector to each value in the second vector, producing a new vector containing all the results.
254 ///
255 /// ### Type Signature
256 ///
257 /// `forall a b. Semiapplicative Vec => (Vec (a -> b), Vec a) -> Vec b`
258 ///
259 /// ### Type Parameters
260 ///
261 /// * `FnBrand`: The brand of the clonable function wrapper.
262 /// * `A`: The type of the input values.
263 /// * `B`: The type of the output values.
264 ///
265 /// ### Parameters
266 ///
267 /// * `ff`: The vector containing the functions.
268 /// * `fa`: The vector containing the values.
269 ///
270 /// ### Returns
271 ///
272 /// A new vector containing the results of applying each function to each value.
273 ///
274 /// ### Examples
275 ///
276 /// ```
277 /// use fp_library::classes::semiapplicative::apply;
278 /// use fp_library::classes::clonable_fn::ClonableFn;
279 /// use fp_library::brands::{VecBrand};
280 /// use fp_library::brands::RcFnBrand;
281 /// use std::rc::Rc;
282 ///
283 /// let funcs = vec![
284 /// <RcFnBrand as ClonableFn>::new(|x: i32| x + 1),
285 /// <RcFnBrand as ClonableFn>::new(|x: i32| x * 2),
286 /// ];
287 /// assert_eq!(apply::<RcFnBrand, VecBrand, _, _>(funcs, vec![1, 2]), vec![2, 3, 2, 4]);
288 /// ```
289 fn apply<'a, FnBrand: 'a + ClonableFn, A: 'a + Clone, B: 'a>(
290 ff: Apply!(brand: Self, signature: ('a, Apply!(brand: FnBrand, kind: ClonableFn, lifetimes: ('a), types: (A, B)): 'a) -> 'a),
291 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
292 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) {
293 ff.iter().flat_map(|f| fa.iter().map(move |a| f(a.clone()))).collect()
294 }
295}
296
297impl Semimonad for VecBrand {
298 /// Chains vector computations (flat_map).
299 ///
300 /// This method applies a function that returns a vector to each element of the input vector, and then flattens the result.
301 ///
302 /// ### Type Signature
303 ///
304 /// `forall a b. Semimonad Vec => (Vec a, a -> Vec b) -> Vec b`
305 ///
306 /// ### Type Parameters
307 ///
308 /// * `F`: The type of the function to apply.
309 /// * `A`: The type of the elements in the input vector.
310 /// * `B`: The type of the elements in the output vector.
311 ///
312 /// ### Parameters
313 ///
314 /// * `ma`: The first vector.
315 /// * `f`: The function to apply to each element, returning a vector.
316 ///
317 /// ### Returns
318 ///
319 /// A new vector containing the flattened results.
320 ///
321 /// ### Examples
322 ///
323 /// ```
324 /// use fp_library::classes::semimonad::bind;
325 /// use fp_library::brands::VecBrand;
326 ///
327 /// assert_eq!(
328 /// bind::<VecBrand, _, _, _>(vec![1, 2], |x| vec![x, x * 2]),
329 /// vec![1, 2, 2, 4]
330 /// );
331 /// ```
332 fn bind<'a, F, A: 'a, B: 'a>(
333 ma: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
334 f: F,
335 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
336 where
337 F: Fn(A) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) + 'a,
338 {
339 ma.into_iter().flat_map(f).collect()
340 }
341}
342
343impl Foldable for VecBrand {
344 /// Folds the vector from the right.
345 ///
346 /// This method performs a right-associative fold of the vector.
347 ///
348 /// ### Type Signature
349 ///
350 /// `forall a b. Foldable Vec => ((a, b) -> b, b, Vec a) -> b`
351 ///
352 /// ### Type Parameters
353 ///
354 /// * `FnBrand`: The brand of the clonable function to use.
355 /// * `Func`: The type of the folding function.
356 /// * `A`: The type of the elements in the vector.
357 /// * `B`: The type of the accumulator.
358 ///
359 /// ### Parameters
360 ///
361 /// * `func`: The folding function.
362 /// * `initial`: The initial value.
363 /// * `fa`: The vector to fold.
364 ///
365 /// ### Returns
366 ///
367 /// The final accumulator value.
368 ///
369 /// ### Examples
370 ///
371 /// ```
372 /// use fp_library::classes::foldable::fold_right;
373 /// use fp_library::brands::VecBrand;
374 /// use fp_library::brands::RcFnBrand;
375 ///
376 /// assert_eq!(fold_right::<RcFnBrand, VecBrand, _, _, _>(|x: i32, acc| x + acc, 0, vec![1, 2, 3]), 6);
377 /// ```
378 fn fold_right<'a, FnBrand, Func, A: 'a, B: 'a>(
379 func: Func,
380 initial: B,
381 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
382 ) -> B
383 where
384 Func: Fn(A, B) -> B + 'a,
385 FnBrand: ClonableFn + 'a,
386 {
387 fa.into_iter().rev().fold(initial, |acc, x| func(x, acc))
388 }
389
390 /// Folds the vector from the left.
391 ///
392 /// This method performs a left-associative fold of the vector.
393 ///
394 /// ### Type Signature
395 ///
396 /// `forall a b. Foldable Vec => ((b, a) -> b, b, Vec a) -> b`
397 ///
398 /// ### Type Parameters
399 ///
400 /// * `FnBrand`: The brand of the clonable function to use.
401 /// * `Func`: The type of the folding function.
402 /// * `A`: The type of the elements in the vector.
403 /// * `B`: The type of the accumulator.
404 ///
405 /// ### Parameters
406 ///
407 /// * `func`: The function to apply to the accumulator and each element.
408 /// * `initial`: The initial value of the accumulator.
409 /// * `fa`: The vector to fold.
410 ///
411 /// ### Returns
412 ///
413 /// The final accumulator value.
414 ///
415 /// ### Examples
416 ///
417 /// ```
418 /// use fp_library::classes::foldable::fold_left;
419 /// use fp_library::brands::VecBrand;
420 /// use fp_library::brands::RcFnBrand;
421 ///
422 /// assert_eq!(fold_left::<RcFnBrand, VecBrand, _, _, _>(|acc, x: i32| acc + x, 0, vec![1, 2, 3]), 6);
423 /// ```
424 fn fold_left<'a, FnBrand, Func, A: 'a, B: 'a>(
425 func: Func,
426 initial: B,
427 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
428 ) -> B
429 where
430 Func: Fn(B, A) -> B + 'a,
431 FnBrand: ClonableFn + 'a,
432 {
433 fa.into_iter().fold(initial, func)
434 }
435
436 /// Maps the values to a monoid and combines them.
437 ///
438 /// This method maps each element of the vector to a monoid and then combines the results using the monoid's `append` operation.
439 ///
440 /// ### Type Signature
441 ///
442 /// `forall a m. (Foldable Vec, Monoid m) => ((a) -> m, Vec a) -> m`
443 ///
444 /// ### Type Parameters
445 ///
446 /// * `FnBrand`: The brand of the clonable function to use.
447 /// * `Func`: The type of the mapping function.
448 /// * `A`: The type of the elements in the vector.
449 /// * `M`: The type of the monoid.
450 ///
451 /// ### Parameters
452 ///
453 /// * `func`: The mapping function.
454 /// * `fa`: The vector to fold.
455 ///
456 /// ### Returns
457 ///
458 /// The combined monoid value.
459 ///
460 /// ### Examples
461 ///
462 /// ```
463 /// use fp_library::classes::foldable::fold_map;
464 /// use fp_library::brands::VecBrand;
465 /// use fp_library::types::string; // Import to bring Monoid impl for String into scope
466 /// use fp_library::brands::RcFnBrand;
467 ///
468 /// assert_eq!(
469 /// fold_map::<RcFnBrand, VecBrand, _, _, _>(|x: i32| x.to_string(), vec![1, 2, 3]),
470 /// "123".to_string()
471 /// );
472 /// ```
473 fn fold_map<'a, FnBrand, Func, A: 'a, M>(
474 func: Func,
475 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
476 ) -> M
477 where
478 M: Monoid + 'a,
479 Func: Fn(A) -> M + 'a,
480 FnBrand: ClonableFn + 'a,
481 {
482 fa.into_iter().map(func).fold(M::empty(), |acc, x| M::append(acc, x))
483 }
484}
485
486impl Traversable for VecBrand {
487 /// Traverses the vector with an applicative function.
488 ///
489 /// This method maps each element of the vector to a computation, evaluates them, and combines the results into an applicative context.
490 ///
491 /// ### Type Signature
492 ///
493 /// `forall a b f. (Traversable Vec, Applicative f) => (a -> f b, Vec a) -> f (Vec b)`
494 ///
495 /// ### Type Parameters
496 ///
497 /// * `F`: The applicative context.
498 /// * `Func`: The type of the function to apply.
499 /// * `A`: The type of the elements in the vector.
500 /// * `B`: The type of the elements in the resulting vector.
501 ///
502 /// ### Parameters
503 ///
504 /// * `func`: The function to apply to each element, returning a value in an applicative context.
505 /// * `ta`: The vector to traverse.
506 ///
507 /// ### Returns
508 ///
509 /// The vector wrapped in the applicative context.
510 ///
511 /// ### Examples
512 ///
513 /// ```
514 /// use fp_library::classes::traversable::traverse;
515 /// use fp_library::brands::{OptionBrand, VecBrand};
516 ///
517 /// assert_eq!(
518 /// traverse::<VecBrand, OptionBrand, _, _, _>(|x| Some(x * 2), vec![1, 2, 3]),
519 /// Some(vec![2, 4, 6])
520 /// );
521 /// ```
522 fn traverse<'a, F: Applicative, Func, A: 'a + Clone, B: 'a + Clone>(
523 func: Func,
524 ta: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
525 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): 'a) -> 'a)
526 where
527 Func: Fn(A) -> Apply!(brand: F, signature: ('a, B: 'a) -> 'a) + 'a,
528 Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): Clone,
529 {
530 let len = ta.len();
531 ta.into_iter().fold(F::pure(Vec::with_capacity(len)), |acc, x| {
532 F::lift2(
533 |mut v, b| {
534 v.push(b);
535 v
536 },
537 acc,
538 func(x),
539 )
540 })
541 }
542 /// Sequences a vector of applicative.
543 ///
544 /// This method evaluates the computations inside the vector and accumulates the results into an applicative context.
545 ///
546 /// ### Type Signature
547 ///
548 /// `forall a f. (Traversable Vec, Applicative f) => (Vec (f a)) -> f (Vec a)`
549 ///
550 /// ### Type Parameters
551 ///
552 /// * `F`: The applicative context.
553 /// * `A`: The type of the elements in the vector.
554 ///
555 /// ### Parameters
556 ///
557 /// * `ta`: The vector containing the applicative values.
558 ///
559 /// ### Returns
560 ///
561 /// The vector wrapped in the applicative context.
562 ///
563 /// ### Examples
564 ///
565 /// ```
566 /// use fp_library::classes::traversable::sequence;
567 /// use fp_library::brands::{OptionBrand, VecBrand};
568 ///
569 /// assert_eq!(
570 /// sequence::<VecBrand, OptionBrand, _>(vec![Some(1), Some(2)]),
571 /// Some(vec![1, 2])
572 /// );
573 /// ```
574 fn sequence<'a, F: Applicative, A: 'a + Clone>(
575 ta: Apply!(brand: Self, signature: ('a, Apply!(brand: F, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
576 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
577 where
578 Apply!(brand: F, signature: ('a, A: 'a) -> 'a): Clone,
579 Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): Clone,
580 {
581 let len = ta.len();
582 ta.into_iter().fold(F::pure(Vec::with_capacity(len)), |acc, x| {
583 F::lift2(
584 |mut v, a| {
585 v.push(a);
586 v
587 },
588 acc,
589 x,
590 )
591 })
592 }
593}
594
595impl<A: Clone> Semigroup for Vec<A> {
596 /// Appends one vector to another.
597 ///
598 /// This method concatenates two vectors.
599 ///
600 /// ### Type Signature
601 ///
602 /// `forall a. Semigroup (Vec a) => (Vec a, Vec a) -> Vec a`
603 ///
604 /// ### Type Parameters
605 ///
606 /// * `A`: The type of the elements in the vector.
607 ///
608 /// ### Parameters
609 ///
610 /// * `a`: The first vector.
611 /// * `b`: The second vector.
612 ///
613 /// ### Returns
614 ///
615 /// The concatenated vector.
616 ///
617 /// ### Examples
618 ///
619 /// ```
620 /// use fp_library::classes::semigroup::append;
621 ///
622 /// assert_eq!(append(vec![1, 2], vec![3, 4]), vec![1, 2, 3, 4]);
623 /// ```
624 fn append(
625 a: Self,
626 b: Self,
627 ) -> Self {
628 [a, b].concat()
629 }
630}
631
632impl<A: Clone> Monoid for Vec<A> {
633 /// Returns an empty vector.
634 ///
635 /// This method returns a new, empty vector.
636 ///
637 /// ### Type Signature
638 ///
639 /// `forall a. Monoid (Vec a) => () -> Vec a`
640 ///
641 /// ### Type Parameters
642 ///
643 /// * `A`: The type of the elements in the vector.
644 ///
645 /// ### Returns
646 ///
647 /// An empty vector.
648 ///
649 /// ### Examples
650 ///
651 /// ```
652 /// use fp_library::classes::monoid::empty;
653 ///
654 /// assert_eq!(empty::<Vec<i32>>(), vec![]);
655 /// ```
656 fn empty() -> Self {
657 Vec::new()
658 }
659}
660
661impl<FnBrand: SendClonableFn> ParFoldable<FnBrand> for VecBrand {
662 /// Maps values to a monoid and combines them in parallel.
663 ///
664 /// This method maps each element of the vector to a monoid and then combines the results using the monoid's `append` operation. The mapping and combination operations may be executed in parallel.
665 ///
666 /// ### Type Signature
667 ///
668 /// `forall a m. (ParFoldable Vec, Monoid m, Send m, Sync m) => (f a m, Vec a) -> m`
669 ///
670 /// ### Type Parameters
671 ///
672 /// * `FnBrand`: The brand of thread-safe function to use (must implement `SendClonableFn`).
673 /// * `A`: The element type (must be `Send + Sync`).
674 /// * `M`: The monoid type (must be `Send + Sync`).
675 ///
676 /// ### Parameters
677 ///
678 /// * `func`: The thread-safe function to map each element to a monoid.
679 /// * `fa`: The vector to fold.
680 ///
681 /// ### Returns
682 ///
683 /// The combined monoid value.
684 ///
685 /// ### Examples
686 ///
687 /// ```
688 /// use fp_library::classes::par_foldable::par_fold_map;
689 /// use fp_library::brands::{VecBrand, ArcFnBrand};
690 /// use fp_library::classes::send_clonable_fn::SendClonableFn;
691 /// use fp_library::types::string;
692 ///
693 /// let v = vec![1, 2, 3];
694 /// let f = <ArcFnBrand as SendClonableFn>::new_send(|x: i32| x.to_string());
695 /// assert_eq!(par_fold_map::<ArcFnBrand, VecBrand, _, _>(f, v), "123".to_string());
696 /// ```
697 fn par_fold_map<'a, A, M>(
698 func: Apply!(brand: FnBrand, kind: SendClonableFn, output: SendOf, lifetimes: ('a), types: (A, M)),
699 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
700 ) -> M
701 where
702 A: 'a + Clone + Send + Sync,
703 M: Monoid + Send + Sync + 'a,
704 {
705 #[cfg(feature = "rayon")]
706 {
707 fa.into_par_iter().map(|a| func(a)).reduce(M::empty, |acc, m| M::append(acc, m))
708 }
709 #[cfg(not(feature = "rayon"))]
710 {
711 #[allow(clippy::redundant_closure)]
712 fa.into_iter().map(|a| func(a)).fold(M::empty(), |acc, m| M::append(acc, m))
713 }
714 }
715}
716
717#[cfg(test)]
718mod tests {
719 use super::*;
720 use crate::{
721 brands::{ArcFnBrand, RcFnBrand},
722 classes::{
723 functor::map,
724 monoid::empty,
725 par_foldable::{par_fold_map, par_fold_right},
726 pointed::pure,
727 semiapplicative::apply,
728 semigroup::append,
729 semimonad::bind,
730 send_clonable_fn::new_send,
731 },
732 functions::{compose, identity},
733 };
734 use quickcheck_macros::quickcheck;
735
736 // Functor Laws
737
738 /// Tests the identity law for Functor.
739 #[quickcheck]
740 fn functor_identity(x: Vec<i32>) -> bool {
741 map::<VecBrand, _, _, _>(identity, x.clone()) == x
742 }
743
744 /// Tests the composition law for Functor.
745 #[quickcheck]
746 fn functor_composition(x: Vec<i32>) -> bool {
747 let f = |x: i32| x.wrapping_add(1);
748 let g = |x: i32| x.wrapping_mul(2);
749 map::<VecBrand, _, _, _>(compose(f, g), x.clone())
750 == map::<VecBrand, _, _, _>(f, map::<VecBrand, _, _, _>(g, x))
751 }
752
753 // Applicative Laws
754
755 /// Tests the identity law for Applicative.
756 #[quickcheck]
757 fn applicative_identity(v: Vec<i32>) -> bool {
758 apply::<RcFnBrand, VecBrand, _, _>(
759 pure::<VecBrand, _>(<RcFnBrand as ClonableFn>::new(identity)),
760 v.clone(),
761 ) == v
762 }
763
764 /// Tests the homomorphism law for Applicative.
765 #[quickcheck]
766 fn applicative_homomorphism(x: i32) -> bool {
767 let f = |x: i32| x.wrapping_mul(2);
768 apply::<RcFnBrand, VecBrand, _, _>(
769 pure::<VecBrand, _>(<RcFnBrand as ClonableFn>::new(f)),
770 pure::<VecBrand, _>(x),
771 ) == pure::<VecBrand, _>(f(x))
772 }
773
774 /// Tests the composition law for Applicative.
775 #[quickcheck]
776 fn applicative_composition(
777 w: Vec<i32>,
778 u_seeds: Vec<i32>,
779 v_seeds: Vec<i32>,
780 ) -> bool {
781 let u_fns: Vec<_> = u_seeds
782 .iter()
783 .map(|&i| <RcFnBrand as ClonableFn>::new(move |x: i32| x.wrapping_add(i)))
784 .collect();
785 let v_fns: Vec<_> = v_seeds
786 .iter()
787 .map(|&i| <RcFnBrand as ClonableFn>::new(move |x: i32| x.wrapping_mul(i)))
788 .collect();
789
790 // RHS: u <*> (v <*> w)
791 let vw = apply::<RcFnBrand, VecBrand, _, _>(v_fns.clone(), w.clone());
792 let rhs = apply::<RcFnBrand, VecBrand, _, _>(u_fns.clone(), vw);
793
794 // LHS: pure(compose) <*> u <*> v <*> w
795 // equivalent to (u . v) <*> w
796 // We construct (u . v) manually as the cartesian product of compositions
797 let uv_fns: Vec<_> = u_fns
798 .iter()
799 .flat_map(|uf| {
800 v_fns.iter().map(move |vf| {
801 let uf = uf.clone();
802 let vf = vf.clone();
803 <RcFnBrand as ClonableFn>::new(move |x| uf(vf(x)))
804 })
805 })
806 .collect();
807
808 let lhs = apply::<RcFnBrand, VecBrand, _, _>(uv_fns, w);
809
810 lhs == rhs
811 }
812
813 /// Tests the interchange law for Applicative.
814 #[quickcheck]
815 fn applicative_interchange(y: i32) -> bool {
816 // u <*> pure y = pure ($ y) <*> u
817 let f = |x: i32| x.wrapping_mul(2);
818 let u = vec![<RcFnBrand as ClonableFn>::new(f)];
819
820 let lhs = apply::<RcFnBrand, VecBrand, _, _>(u.clone(), pure::<VecBrand, _>(y));
821
822 let rhs_fn = <RcFnBrand as ClonableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
823 let rhs = apply::<RcFnBrand, VecBrand, _, _>(pure::<VecBrand, _>(rhs_fn), u);
824
825 lhs == rhs
826 }
827
828 // Semigroup Laws
829
830 /// Tests the associativity law for Semigroup.
831 #[quickcheck]
832 fn semigroup_associativity(
833 a: Vec<i32>,
834 b: Vec<i32>,
835 c: Vec<i32>,
836 ) -> bool {
837 append(a.clone(), append(b.clone(), c.clone())) == append(append(a, b), c)
838 }
839
840 // Monoid Laws
841
842 /// Tests the left identity law for Monoid.
843 #[quickcheck]
844 fn monoid_left_identity(a: Vec<i32>) -> bool {
845 append(empty::<Vec<i32>>(), a.clone()) == a
846 }
847
848 /// Tests the right identity law for Monoid.
849 #[quickcheck]
850 fn monoid_right_identity(a: Vec<i32>) -> bool {
851 append(a.clone(), empty::<Vec<i32>>()) == a
852 }
853
854 // Monad Laws
855
856 /// Tests the left identity law for Monad.
857 #[quickcheck]
858 fn monad_left_identity(a: i32) -> bool {
859 let f = |x: i32| vec![x.wrapping_mul(2)];
860 bind::<VecBrand, _, _, _>(pure::<VecBrand, _>(a), f) == f(a)
861 }
862
863 /// Tests the right identity law for Monad.
864 #[quickcheck]
865 fn monad_right_identity(m: Vec<i32>) -> bool {
866 bind::<VecBrand, _, _, _>(m.clone(), pure::<VecBrand, _>) == m
867 }
868
869 /// Tests the associativity law for Monad.
870 #[quickcheck]
871 fn monad_associativity(m: Vec<i32>) -> bool {
872 let f = |x: i32| vec![x.wrapping_mul(2)];
873 let g = |x: i32| vec![x.wrapping_add(1)];
874 bind::<VecBrand, _, _, _>(bind::<VecBrand, _, _, _>(m.clone(), f), g)
875 == bind::<VecBrand, _, _, _>(m, |x| bind::<VecBrand, _, _, _>(f(x), g))
876 }
877
878 // Edge Cases
879
880 /// Tests `map` on an empty vector.
881 #[test]
882 fn map_empty() {
883 assert_eq!(
884 map::<VecBrand, _, _, _>(|x: i32| x + 1, vec![] as Vec<i32>),
885 vec![] as Vec<i32>
886 );
887 }
888
889 /// Tests `bind` on an empty vector.
890 #[test]
891 fn bind_empty() {
892 assert_eq!(
893 bind::<VecBrand, _, _, _>(vec![] as Vec<i32>, |x: i32| vec![x + 1]),
894 vec![] as Vec<i32>
895 );
896 }
897
898 /// Tests `bind` returning an empty vector.
899 #[test]
900 fn bind_returning_empty() {
901 assert_eq!(
902 bind::<VecBrand, _, _, _>(vec![1, 2, 3], |_| vec![] as Vec<i32>),
903 vec![] as Vec<i32>
904 );
905 }
906
907 /// Tests `fold_right` on an empty vector.
908 #[test]
909 fn fold_right_empty() {
910 assert_eq!(
911 crate::classes::foldable::fold_right::<RcFnBrand, VecBrand, _, _, _>(
912 |x: i32, acc| x + acc,
913 0,
914 vec![]
915 ),
916 0
917 );
918 }
919
920 /// Tests `fold_left` on an empty vector.
921 #[test]
922 fn fold_left_empty() {
923 assert_eq!(
924 crate::classes::foldable::fold_left::<RcFnBrand, VecBrand, _, _, _>(
925 |acc, x: i32| acc + x,
926 0,
927 vec![]
928 ),
929 0
930 );
931 }
932
933 /// Tests `traverse` on an empty vector.
934 #[test]
935 fn traverse_empty() {
936 use crate::brands::OptionBrand;
937 assert_eq!(
938 crate::classes::traversable::traverse::<VecBrand, OptionBrand, _, _, _>(
939 |x: i32| Some(x + 1),
940 vec![]
941 ),
942 Some(vec![])
943 );
944 }
945
946 /// Tests `traverse` returning an empty vector.
947 #[test]
948 fn traverse_returning_empty() {
949 use crate::brands::OptionBrand;
950 assert_eq!(
951 crate::classes::traversable::traverse::<VecBrand, OptionBrand, _, _, _>(
952 |_: i32| None::<i32>,
953 vec![1, 2, 3]
954 ),
955 None
956 );
957 }
958
959 /// Tests `construct` with an empty tail.
960 #[test]
961 fn construct_empty_tail() {
962 assert_eq!(VecBrand::construct(1, vec![]), vec![1]);
963 }
964
965 /// Tests `deconstruct` on an empty slice.
966 #[test]
967 fn deconstruct_empty() {
968 assert_eq!(VecBrand::deconstruct::<i32>(&[]), None);
969 }
970
971 // ParFoldable Tests
972
973 /// Tests `par_fold_map` on an empty vector.
974 #[test]
975 fn par_fold_map_empty() {
976 let v: Vec<i32> = vec![];
977 let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
978 assert_eq!(par_fold_map::<ArcFnBrand, VecBrand, _, _>(f, v), "".to_string());
979 }
980
981 /// Tests `par_fold_map` on a single element.
982 #[test]
983 fn par_fold_map_single() {
984 let v = vec![1];
985 let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
986 assert_eq!(par_fold_map::<ArcFnBrand, VecBrand, _, _>(f, v), "1".to_string());
987 }
988
989 /// Tests `par_fold_map` on multiple elements.
990 #[test]
991 fn par_fold_map_multiple() {
992 let v = vec![1, 2, 3];
993 let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
994 assert_eq!(par_fold_map::<ArcFnBrand, VecBrand, _, _>(f, v), "123".to_string());
995 }
996
997 /// Tests `par_fold_right` on multiple elements.
998 #[test]
999 fn par_fold_right_multiple() {
1000 let v = vec![1, 2, 3];
1001 let f = new_send::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1002 assert_eq!(par_fold_right::<ArcFnBrand, VecBrand, _, _>(f, 0, v), 6);
1003 }
1004}