fp_library/types/
vec.rs

1//! Implementations for [`Vec`].
2
3pub mod concrete_vec;
4
5use crate::{
6	classes::{
7		Applicative, ApplyFirst, ApplySecond, ClonableFn, Foldable, Functor, Pointed,
8		Semiapplicative, Semimonad, Traversable, clonable_fn::ApplyFn,
9	},
10	functions::{apply, map, pure, traverse},
11	hkt::{Apply0L1T, Kind0L1T},
12	types::Pair,
13};
14
15pub struct VecBrand;
16
17impl Kind0L1T for VecBrand {
18	type Output<A> = Vec<A>;
19}
20
21impl VecBrand {
22	/// Constructs a new vector by prepending a value to an existing vector.
23	///
24	/// # Type Signature
25	///
26	/// `forall a. a -> Vec a -> Vec a`
27	///
28	/// # Parameters
29	///
30	/// * `head`: A value to prepend to the vector.
31	/// * `tail`: A vector to prepend the value to.
32	///
33	/// # Returns
34	///
35	/// A new vector consisting of the `head` element prepended to the `tail` vector.
36	///
37	/// # Examples
38	///
39	/// ```
40	/// use fp_library::brands::{RcFnBrand, VecBrand};
41	///
42	/// let head = 1;
43	/// let tail = vec![2, 3];
44	/// let new_vec = (VecBrand::construct::<RcFnBrand, _>(head))(tail);
45	/// assert_eq!(new_vec, vec![1, 2, 3]);
46	///
47	/// let empty_tail = vec![];
48	/// let single_element = (VecBrand::construct::<RcFnBrand, _>(42))(empty_tail);
49	/// assert_eq!(single_element, vec![42]);
50	/// ```
51	pub fn construct<'a, ClonableFnBrand: 'a + ClonableFn, A>(
52		head: A
53	) -> ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, Apply0L1T<Self, A>>
54	where
55		A: Clone,
56	{
57		ClonableFnBrand::new(move |tail| [vec![head.to_owned()], tail].concat())
58	}
59
60	/// Deconstructs a slice into its head element and tail vector.
61	///
62	/// # Type Signature
63	///
64	/// `forall a. &[a] -> Option (Pair a (Vec a))`
65	///
66	/// # Parameters
67	///
68	/// * `slice`: The vector slice to deconstruct.
69	///
70	/// # Returns
71	///
72	/// An [`Option`] containing a [`Pair`] of the head element and the remaining tail vector,
73	/// or [`None`] if the slice is empty.
74	///
75	/// # Examples
76	///
77	/// ```
78	/// use fp_library::{brands::VecBrand, types::Pair};
79	///
80	/// let vec = vec![1, 2, 3];
81	/// let deconstructed = VecBrand::deconstruct(&vec);
82	/// assert_eq!(deconstructed, Some(Pair(1, vec![2, 3])));
83	///
84	/// let empty: Vec<i32> = vec![];
85	/// assert_eq!(VecBrand::deconstruct(&empty), None);
86	/// ```
87	pub fn deconstruct<A>(slice: &[A]) -> Option<Pair<A, Apply0L1T<Self, A>>>
88	where
89		A: Clone,
90	{
91		match &slice {
92			[] => None,
93			[head, tail @ ..] => Some(Pair(head.to_owned(), tail.to_owned())),
94		}
95	}
96}
97
98impl Functor for VecBrand {
99	/// # Examples
100	///
101	/// ```
102	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::{identity, map}};
103	/// use std::rc::Rc;
104	///
105	/// assert_eq!(
106	///     map::<RcFnBrand, VecBrand, _, _>(Rc::new(identity))(vec![] as Vec<()>),
107	///     vec![]
108	/// );
109	/// assert_eq!(
110	///     map::<RcFnBrand, VecBrand, _, _>(Rc::new(|x: i32| x * 2))(vec![1, 2, 3]),
111	///     vec![2, 4, 6]
112	/// );
113	/// ```
114	fn map<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a, B: 'a>(
115		f: ApplyFn<'a, ClonableFnBrand, A, B>
116	) -> ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, Apply0L1T<Self, B>> {
117		ClonableFnBrand::new(move |fa: Apply0L1T<Self, _>| fa.into_iter().map(&*f).collect())
118	}
119}
120
121impl Semiapplicative for VecBrand {
122	/// # Examples
123	///
124	/// ```
125	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::{apply, identity}};
126	/// use std::rc::Rc;
127	///
128	/// assert_eq!(
129	///     apply::<RcFnBrand, VecBrand, _, _>(vec![] as Vec<Rc<dyn Fn(i32) -> i32>>)(vec![1, 2, 3]),
130	///     vec![] as Vec<i32>
131	/// );
132	/// assert_eq!(
133	///     apply::<RcFnBrand, VecBrand, _, _>(vec![Rc::new(identity), Rc::new(|x: i32| x * 2)])(vec![1, 2]),
134	///     vec![1, 2, 2, 4]
135	/// );
136	/// ```
137	fn apply<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: 'a>(
138		ff: Apply0L1T<Self, ApplyFn<'a, ClonableFnBrand, A, B>>
139	) -> ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, Apply0L1T<Self, B>> {
140		ClonableFnBrand::new(move |fa: Apply0L1T<Self, _>| {
141			ff.iter()
142				.cloned()
143				.flat_map(|f| fa.iter().cloned().map(&*f).collect::<Vec<_>>())
144				.collect()
145		})
146	}
147}
148
149impl ApplyFirst for VecBrand {
150	/// # Examples
151	///
152	/// ```
153	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::apply_first};
154	/// use std::rc::Rc;
155	///
156	/// assert_eq!(
157	///     apply_first::<RcFnBrand, VecBrand, _, _>(vec![] as Vec<i32>)(vec![1, 2]),
158	///     vec![] as Vec<i32>
159	/// );
160	/// assert_eq!(
161	///     apply_first::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(vec![] as Vec<i32>),
162	///     vec![] as Vec<i32>
163	/// );
164	/// assert_eq!(
165	///     apply_first::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(vec![3, 4]),
166	///     vec![1, 1, 2, 2]
167	/// );
168	/// ```
169	fn apply_first<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: Clone>(
170		fa: Apply0L1T<Self, A>
171	) -> ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, B>, Apply0L1T<Self, A>> {
172		ClonableFnBrand::new(move |fb: Apply0L1T<Self, _>| {
173			fa.iter().cloned().flat_map(|a| fb.iter().map(move |_b| a.to_owned())).collect()
174		})
175	}
176}
177
178impl ApplySecond for VecBrand {
179	/// # Examples
180	///
181	/// ```
182	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::apply_second};
183	/// use std::rc::Rc;
184	///
185	/// assert_eq!(
186	///     apply_second::<RcFnBrand, VecBrand, _, _>(vec![] as Vec<i32>)(vec![1, 2]),
187	///     vec![] as Vec<i32>
188	/// );
189	/// assert_eq!(
190	///     apply_second::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(vec![] as Vec<i32>),
191	///     vec![] as Vec<i32>
192	/// );
193	/// assert_eq!(
194	///     apply_second::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(vec![3, 4]),
195	///     vec![3, 4, 3, 4]
196	/// );
197	/// ```
198	fn apply_second<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: 'a + Clone>(
199		fa: Apply0L1T<Self, A>
200	) -> ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, B>, Apply0L1T<Self, B>> {
201		ClonableFnBrand::new(move |fb: Apply0L1T<Self, _>| {
202			fa.iter().cloned().flat_map(|_a| fb.iter().cloned()).collect()
203		})
204	}
205}
206
207impl Pointed for VecBrand {
208	/// # Examples
209	///
210	/// ```
211	/// use fp_library::{brands::{RcFnBrand, VecBrand}, functions::pure};
212	///
213	/// assert_eq!(
214	///     pure::<RcFnBrand, VecBrand, _>(1),
215	///     vec![1]
216	/// );
217	/// ```
218	fn pure<ClonableFnBrand: ClonableFn, A: Clone>(a: A) -> Apply0L1T<Self, A> {
219		vec![a]
220	}
221}
222
223impl Semimonad for VecBrand {
224	/// # Examples
225	///
226	/// ```
227	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::{bind, pure}};
228	/// use std::rc::Rc;
229	///
230	/// assert_eq!(
231	///     bind::<RcFnBrand, VecBrand, _, _>(vec![] as Vec<()>)(Rc::new(|_| pure::<RcFnBrand, VecBrand, _>(1))),
232	///     vec![] as Vec<i32>
233	/// );
234	/// assert_eq!(
235	///     bind::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(Rc::new(|x| vec![x, x * 2])),
236	///     vec![1, 2, 2, 4]
237	/// );
238	/// ```
239	fn bind<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: Clone>(
240		ma: Apply0L1T<Self, A>
241	) -> ApplyFn<
242		'a,
243		ClonableFnBrand,
244		ApplyFn<'a, ClonableFnBrand, A, Apply0L1T<Self, B>>,
245		Apply0L1T<Self, B>,
246	> {
247		ClonableFnBrand::new(move |f: ApplyFn<'a, ClonableFnBrand, _, _>| {
248			ma.iter().cloned().flat_map(&*f).collect()
249		})
250	}
251}
252
253impl Foldable for VecBrand {
254	/// # Examples
255	///
256	/// ```
257	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::fold_right};
258	/// use std::rc::Rc;
259	///
260	/// assert_eq!(
261	///     fold_right::<RcFnBrand, VecBrand, _, _>(Rc::new(|item| Rc::new(move |carry| carry * 2 + item)))(0)(vec![1, 2, 3]),
262	///     17
263	/// );
264	/// ```
265	fn fold_right<'a, ClonableFnBrand: 'a + ClonableFn, A: Clone, B: Clone>(
266		f: ApplyFn<'a, ClonableFnBrand, A, ApplyFn<'a, ClonableFnBrand, B, B>>
267	) -> ApplyFn<'a, ClonableFnBrand, B, ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, B>> {
268		ClonableFnBrand::new(move |b: B| {
269			let f = f.clone();
270			ClonableFnBrand::new(move |fa: Apply0L1T<Self, A>| {
271				fa.iter().rfold(b.to_owned(), {
272					let f = f.clone();
273					let f = move |b, a| f(a)(b);
274					move |b, a| f(b, a.to_owned())
275				})
276			})
277		})
278	}
279}
280
281impl Traversable for VecBrand {
282	// traverse f Vec.empty = pure Vec.empty
283	// traverse f (Vec.construct head tail) = (apply ((map Vec.construct) (f head))) ((traverse f) tail)
284	/// # Examples
285	///
286	/// ```
287	/// use fp_library::{brands::{VecBrand, RcFnBrand, OptionBrand}, functions::traverse};
288	/// use std::rc::Rc;
289	///
290	/// assert_eq!(
291	///     traverse::<RcFnBrand, VecBrand, OptionBrand, i32, i32>(Rc::new(|x| Some(x * 2)))(vec![1, 2, 3]),
292	///     Some(vec![2, 4, 6])
293	/// );
294	/// assert_eq!(
295	///     traverse::<RcFnBrand, VecBrand, OptionBrand, i32, i32>(Rc::new(|_x| None))(vec![1, 2, 3]),
296	///     None
297	/// );
298	/// ```
299	fn traverse<'a, ClonableFnBrand: 'a + ClonableFn, F: Applicative, A: Clone, B: 'a + Clone>(
300		f: ApplyFn<'a, ClonableFnBrand, A, Apply0L1T<F, B>>
301	) -> ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, Apply0L1T<F, Apply0L1T<Self, B>>>
302	where
303		Apply0L1T<F, B>: Clone,
304		Apply0L1T<F, ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, B>, Apply0L1T<Self, B>>>: Clone,
305		Apply0L1T<Self, B>: 'a,
306		Apply0L1T<Self, Apply0L1T<F, B>>: 'a,
307	{
308		ClonableFnBrand::new(move |ta: Apply0L1T<Self, _>| {
309			match VecBrand::deconstruct(&ta) {
310				None => pure::<ClonableFnBrand, F, _>(vec![]),
311				Some(Pair(head, tail)) => {
312					// cons: a -> (t a -> t a)
313					let cons = ClonableFnBrand::new(VecBrand::construct::<ClonableFnBrand, _>);
314					// map: (a -> b) -> f a -> f b
315					// cons: a -> (t a -> t a)
316					// map cons = f a -> f (t a -> t a)
317					let map_cons = map::<ClonableFnBrand, F, _, _>(cons);
318					// f: a -> f b
319					// head: a
320					// f head: f b
321					let f_head = f(head);
322					// traverse: (a -> f b) -> t a -> f (t b)
323					// f: a -> f b
324					// traverse f: t a -> f (t b)
325					let traverse_f = traverse::<ClonableFnBrand, Self, F, _, _>(f.clone());
326					// traverse f: t a -> f (t b)
327					// tail: t a
328					// (traverse f) tail: f (t b)
329					let traverse_f_tail = traverse_f(tail);
330					// map cons: f a -> f (t a -> t a)
331					// f head: f b
332					// (map cons) (f head): f (t b -> t b)
333					let map_cons_f_head = map_cons(f_head);
334					// apply: f (a -> b) -> f a -> f b
335					// (map cons) (f head): f (t b -> t b)
336					// apply ((map cons) (f head)): f (t b) -> f (t b)
337					let apply_map_cons_f_head = apply::<ClonableFnBrand, F, _, _>(map_cons_f_head);
338					// apply ((map cons) (f head)): f (t b) -> f (t b)
339					// (traverse f) tail: f (t b)
340					// apply ((map cons) (f head)) ((traverse f) tail): f (t b)
341					apply_map_cons_f_head(traverse_f_tail)
342				}
343			}
344		})
345	}
346}