fp_library/types/
vec.rs

1//! Implementations for [`Vec`].
2
3use crate::{
4	brands::{Brand, Brand1},
5	hkt::{Apply, Kind, Kind1},
6	typeclasses::{Apply as TypeclassApply, ApplyFirst, ApplySecond, Bind, Functor, Pure},
7};
8
9/// [Brand][crate::brands] for [`Vec`].
10pub struct VecBrand;
11
12impl<A> Kind1<A> for VecBrand {
13	type Output = Vec<A>;
14}
15
16impl<A> Brand1<Vec<A>, A> for VecBrand {
17	fn inject(a: Vec<A>) -> Apply<Self, (A,)> {
18		a
19	}
20	fn project(a: Apply<Self, (A,)>) -> Vec<A> {
21		a
22	}
23}
24
25impl Pure for VecBrand {
26	/// # Examples
27	///
28	/// ```
29	/// use fp_library::{brands::VecBrand, functions::pure};
30	///
31	/// assert_eq!(pure::<VecBrand, _>(1), vec![1]);
32	/// ```
33	fn pure<A>(a: A) -> Apply<Self, (A,)>
34	where
35		Self: Kind<(A,)>,
36	{
37		<Self as Brand<Vec<A>, (A,)>>::inject(vec![a])
38	}
39}
40
41impl Functor for VecBrand {
42	/// # Examples
43	///
44	/// ```
45	/// use fp_library::{brands::VecBrand, functions::{identity, map}};
46	///
47	/// assert_eq!(map::<VecBrand, _, _, _>(identity)(vec![] as Vec<()>), vec![]);
48	/// assert_eq!(map::<VecBrand, _, _, _>(|x: i32| x * 2)(vec![1, 2, 3]), vec![2, 4, 6]);
49	/// ```
50	fn map<F, A, B>(f: F) -> impl Fn(Apply<Self, (A,)>) -> Apply<Self, (B,)>
51	where
52		Self: Kind<(A,)> + Kind<(B,)>,
53		F: Fn(A) -> B,
54	{
55		move |fa| {
56			<Self as Brand<_, (_,)>>::inject(
57				<Self as Brand<_, (_,)>>::project(fa).into_iter().map(&f).collect(),
58			)
59		}
60	}
61}
62
63impl TypeclassApply for VecBrand {
64	/// # Examples
65	///
66	/// ```
67	/// use fp_library::{brands::VecBrand, functions::{apply, identity}};
68	///
69	/// assert_eq!(apply::<VecBrand, _, _, _>(vec![] as Vec<fn(i32) -> i32>)(vec![1, 2, 3]), vec![] as Vec<i32>);
70	/// assert_eq!(apply::<VecBrand, _, _, _>(vec![identity, |x: i32| x * 2])(vec![1, 2]), vec![1, 2, 2, 4]);
71	/// ```
72	fn apply<F, A, B>(ff: Apply<Self, (F,)>) -> impl Fn(Apply<Self, (A,)>) -> Apply<Self, (B,)>
73	where
74		Self: Kind<(F,)> + Kind<(A,)> + Kind<(B,)>,
75		F: Fn(A) -> B,
76		A: Clone,
77		Apply<Self, (F,)>: Clone,
78	{
79		move |fa| {
80			let fa = <Self as Brand<_, (_,)>>::project(fa);
81			<Self as Brand<_, (_,)>>::inject(
82				<Self as Brand<_, (F,)>>::project(ff.to_owned())
83					.into_iter()
84					.flat_map(|f| fa.iter().cloned().map(f))
85					.collect(),
86			)
87		}
88	}
89}
90
91impl ApplyFirst for VecBrand {
92	/// # Examples
93	///
94	/// ```
95	/// use fp_library::{brands::VecBrand, functions::apply_first};
96	///
97	/// assert_eq!(apply_first::<VecBrand, _, _>(vec![] as Vec<i32>)(vec![1, 2]), vec![] as Vec<i32>);
98	/// assert_eq!(apply_first::<VecBrand, _, _>(vec![1, 2])(vec![] as Vec<i32>), vec![] as Vec<i32>);
99	/// assert_eq!(apply_first::<VecBrand, _, _>(vec![1, 2])(vec![3, 4]), vec![1, 1, 2, 2]);
100	/// ```
101	fn apply_first<A, B>(fa: Apply<Self, (A,)>) -> impl Fn(Apply<Self, (B,)>) -> Apply<Self, (A,)>
102	where
103		Self: Kind<(A,)> + Kind<(B,)>,
104		A: Clone,
105		B: Clone,
106		Apply<Self, (A,)>: Clone,
107	{
108		move |fb| {
109			let fb = <Self as Brand<_, (B,)>>::project(fb);
110			<Self as Brand<_, (_,)>>::inject(
111				<Self as Brand<_, (A,)>>::project(fa.to_owned())
112					.into_iter()
113					.flat_map(|a| fb.iter().cloned().map(move |_b| a.to_owned()))
114					.collect(),
115			)
116		}
117	}
118}
119
120impl ApplySecond for VecBrand {
121	/// # Examples
122	///
123	/// ```
124	/// use fp_library::{brands::VecBrand, functions::apply_second};
125	///
126	/// assert_eq!(apply_second::<VecBrand, _, _>(vec![] as Vec<i32>)(vec![1, 2]), vec![] as Vec<i32>);
127	/// assert_eq!(apply_second::<VecBrand, _, _>(vec![1, 2])(vec![] as Vec<i32>), vec![] as Vec<i32>);
128	/// assert_eq!(apply_second::<VecBrand, _, _>(vec![1, 2])(vec![3, 4]), vec![3, 4, 3, 4]);
129	/// ```
130	fn apply_second<A, B>(fa: Apply<Self, (A,)>) -> impl Fn(Apply<Self, (B,)>) -> Apply<Self, (B,)>
131	where
132		Self: Kind<(A,)> + Kind<(B,)>,
133		Apply<Self, (A,)>: Clone,
134		B: Clone,
135	{
136		move |fb| {
137			let fb = <Self as Brand<_, (B,)>>::project(fb);
138			<Self as Brand<_, (_,)>>::inject(
139				<Self as Brand<_, (A,)>>::project(fa.to_owned())
140					.into_iter()
141					.flat_map(|_a| fb.iter().cloned())
142					.collect(),
143			)
144		}
145	}
146}
147
148impl Bind for VecBrand {
149	/// # Examples
150	///
151	/// ```
152	/// use fp_library::{brands::VecBrand, functions::{bind, pure}};
153	///
154	/// assert_eq!(bind::<VecBrand, _, _, _>(vec![] as Vec<()>)(|_| pure::<VecBrand, _>(1)), vec![] as Vec<i32>);
155	/// assert_eq!(bind::<VecBrand, _, _, _>(vec![1, 2])(|x| vec![x, x * 2]), vec![1, 2, 2, 4]);
156	/// ```
157	fn bind<F, A, B>(ma: Apply<Self, (A,)>) -> impl Fn(F) -> Apply<Self, (B,)>
158	where
159		Self: Kind<(A,)> + Kind<(B,)> + Sized,
160		F: Fn(A) -> Apply<Self, (B,)>,
161		Apply<Self, (A,)>: Clone,
162	{
163		move |f| {
164			<Self as Brand<_, (_,)>>::inject(
165				<Self as Brand<_, (_,)>>::project(ma.to_owned())
166					.into_iter()
167					.flat_map(|a| <Self as Brand<_, (B,)>>::project(f(a)))
168					.collect(),
169			)
170		}
171	}
172}