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}