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::ApplyClonableFn,
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	) -> ApplyClonableFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, Apply0L1T<Self, A>>
54	where
55		A: Clone,
56	{
57		<ClonableFnBrand as ClonableFn>::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: ApplyClonableFn<'a, ClonableFnBrand, A, B>
116	) -> ApplyClonableFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, Apply0L1T<Self, B>> {
117		<ClonableFnBrand as ClonableFn>::new(move |fa: Apply0L1T<Self, _>| {
118			fa.into_iter().map(&*f).collect()
119		})
120	}
121}
122
123impl Semiapplicative for VecBrand {
124	/// # Examples
125	///
126	/// ```
127	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::{apply, identity}};
128	/// use std::rc::Rc;
129	///
130	/// assert_eq!(
131	///     apply::<RcFnBrand, VecBrand, _, _>(vec![] as Vec<Rc<dyn Fn(i32) -> i32>>)(vec![1, 2, 3]),
132	///     vec![] as Vec<i32>
133	/// );
134	/// assert_eq!(
135	///     apply::<RcFnBrand, VecBrand, _, _>(vec![Rc::new(identity), Rc::new(|x: i32| x * 2)])(vec![1, 2]),
136	///     vec![1, 2, 2, 4]
137	/// );
138	/// ```
139	fn apply<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: 'a>(
140		ff: Apply0L1T<Self, ApplyClonableFn<'a, ClonableFnBrand, A, B>>
141	) -> ApplyClonableFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, Apply0L1T<Self, B>> {
142		<ClonableFnBrand as ClonableFn>::new(move |fa: Apply0L1T<Self, _>| {
143			ff.iter()
144				.cloned()
145				.flat_map(|f| fa.iter().cloned().map(&*f).collect::<Vec<_>>())
146				.collect()
147		})
148	}
149}
150
151impl ApplyFirst for VecBrand {
152	/// # Examples
153	///
154	/// ```
155	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::apply_first};
156	/// use std::rc::Rc;
157	///
158	/// assert_eq!(
159	///     apply_first::<RcFnBrand, VecBrand, _, _>(vec![] as Vec<i32>)(vec![1, 2]),
160	///     vec![] as Vec<i32>
161	/// );
162	/// assert_eq!(
163	///     apply_first::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(vec![] as Vec<i32>),
164	///     vec![] as Vec<i32>
165	/// );
166	/// assert_eq!(
167	///     apply_first::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(vec![3, 4]),
168	///     vec![1, 1, 2, 2]
169	/// );
170	/// ```
171	fn apply_first<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: Clone>(
172		fa: Apply0L1T<Self, A>
173	) -> ApplyClonableFn<'a, ClonableFnBrand, Apply0L1T<Self, B>, Apply0L1T<Self, A>> {
174		<ClonableFnBrand as ClonableFn>::new(move |fb: Apply0L1T<Self, _>| {
175			fa.iter().cloned().flat_map(|a| fb.iter().map(move |_b| a.to_owned())).collect()
176		})
177	}
178}
179
180impl ApplySecond for VecBrand {
181	/// # Examples
182	///
183	/// ```
184	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::apply_second};
185	/// use std::rc::Rc;
186	///
187	/// assert_eq!(
188	///     apply_second::<RcFnBrand, VecBrand, _, _>(vec![] as Vec<i32>)(vec![1, 2]),
189	///     vec![] as Vec<i32>
190	/// );
191	/// assert_eq!(
192	///     apply_second::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(vec![] as Vec<i32>),
193	///     vec![] as Vec<i32>
194	/// );
195	/// assert_eq!(
196	///     apply_second::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(vec![3, 4]),
197	///     vec![3, 4, 3, 4]
198	/// );
199	/// ```
200	fn apply_second<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: 'a + Clone>(
201		fa: Apply0L1T<Self, A>
202	) -> ApplyClonableFn<'a, ClonableFnBrand, Apply0L1T<Self, B>, Apply0L1T<Self, B>> {
203		<ClonableFnBrand as ClonableFn>::new(move |fb: Apply0L1T<Self, _>| {
204			fa.iter().cloned().flat_map(|_a| fb.iter().cloned()).collect()
205		})
206	}
207}
208
209impl Pointed for VecBrand {
210	/// # Examples
211	///
212	/// ```
213	/// use fp_library::{brands::{RcFnBrand, VecBrand}, functions::pure};
214	///
215	/// assert_eq!(
216	///     pure::<RcFnBrand, VecBrand, _>(1),
217	///     vec![1]
218	/// );
219	/// ```
220	fn pure<ClonableFnBrand: ClonableFn, A: Clone>(a: A) -> Apply0L1T<Self, A> {
221		vec![a]
222	}
223}
224
225impl Semimonad for VecBrand {
226	/// # Examples
227	///
228	/// ```
229	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::{bind, pure}};
230	/// use std::rc::Rc;
231	///
232	/// assert_eq!(
233	///     bind::<RcFnBrand, VecBrand, _, _>(vec![] as Vec<()>)(Rc::new(|_| pure::<RcFnBrand, VecBrand, _>(1))),
234	///     vec![] as Vec<i32>
235	/// );
236	/// assert_eq!(
237	///     bind::<RcFnBrand, VecBrand, _, _>(vec![1, 2])(Rc::new(|x| vec![x, x * 2])),
238	///     vec![1, 2, 2, 4]
239	/// );
240	/// ```
241	fn bind<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B: Clone>(
242		ma: Apply0L1T<Self, A>
243	) -> ApplyClonableFn<
244		'a,
245		ClonableFnBrand,
246		ApplyClonableFn<'a, ClonableFnBrand, A, Apply0L1T<Self, B>>,
247		Apply0L1T<Self, B>,
248	> {
249		<ClonableFnBrand as ClonableFn>::new(
250			move |f: ApplyClonableFn<'a, ClonableFnBrand, _, _>| {
251				ma.iter().cloned().flat_map(&*f).collect()
252			},
253		)
254	}
255}
256
257impl Foldable for VecBrand {
258	/// # Examples
259	///
260	/// ```
261	/// use fp_library::{brands::{VecBrand, RcFnBrand}, functions::fold_right};
262	/// use std::rc::Rc;
263	///
264	/// assert_eq!(
265	///     fold_right::<RcFnBrand, VecBrand, _, _>(Rc::new(|item| Rc::new(move |carry| carry * 2 + item)))(0)(vec![1, 2, 3]),
266	///     17
267	/// );
268	/// ```
269	fn fold_right<'a, ClonableFnBrand: 'a + ClonableFn, A: Clone, B: Clone>(
270		f: ApplyClonableFn<'a, ClonableFnBrand, A, ApplyClonableFn<'a, ClonableFnBrand, B, B>>
271	) -> ApplyClonableFn<
272		'a,
273		ClonableFnBrand,
274		B,
275		ApplyClonableFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, B>,
276	> {
277		<ClonableFnBrand as ClonableFn>::new(move |b: B| {
278			let f = f.clone();
279			<ClonableFnBrand as ClonableFn>::new(move |fa: Apply0L1T<Self, A>| {
280				fa.iter().rfold(b.to_owned(), {
281					let f = f.clone();
282					let f = move |b, a| f(a)(b);
283					move |b, a| f(b, a.to_owned())
284				})
285			})
286		})
287	}
288}
289
290impl Traversable for VecBrand {
291	// traverse f Vec.empty = pure Vec.empty
292	// traverse f (Vec.construct head tail) = (apply ((map Vec.construct) (f head))) ((traverse f) tail)
293	/// # Examples
294	///
295	/// ```
296	/// use fp_library::{brands::{VecBrand, RcFnBrand, OptionBrand}, functions::traverse};
297	/// use std::rc::Rc;
298	///
299	/// assert_eq!(
300	///     traverse::<RcFnBrand, VecBrand, OptionBrand, i32, i32>(Rc::new(|x| Some(x * 2)))(vec![1, 2, 3]),
301	///     Some(vec![2, 4, 6])
302	/// );
303	/// assert_eq!(
304	///     traverse::<RcFnBrand, VecBrand, OptionBrand, i32, i32>(Rc::new(|_x| None))(vec![1, 2, 3]),
305	///     None
306	/// );
307	/// ```
308	fn traverse<'a, ClonableFnBrand: 'a + ClonableFn, F: Applicative, A: Clone, B: 'a + Clone>(
309		f: ApplyClonableFn<'a, ClonableFnBrand, A, Apply0L1T<F, B>>
310	) -> ApplyClonableFn<'a, ClonableFnBrand, Apply0L1T<Self, A>, Apply0L1T<F, Apply0L1T<Self, B>>>
311	where
312		Apply0L1T<F, B>: Clone,
313		Apply0L1T<F, ApplyClonableFn<'a, ClonableFnBrand, Apply0L1T<Self, B>, Apply0L1T<Self, B>>>:
314			Clone,
315		Apply0L1T<Self, B>: 'a,
316		Apply0L1T<Self, Apply0L1T<F, B>>: 'a,
317	{
318		<ClonableFnBrand as ClonableFn>::new(move |ta: Apply0L1T<Self, _>| {
319			match VecBrand::deconstruct(&ta) {
320				None => pure::<ClonableFnBrand, F, _>(vec![]),
321				Some(Pair(head, tail)) => {
322					// cons: a -> (t a -> t a)
323					let cons = <ClonableFnBrand as ClonableFn>::new(
324						VecBrand::construct::<ClonableFnBrand, _>,
325					);
326					// map: (a -> b) -> f a -> f b
327					// cons: a -> (t a -> t a)
328					// map cons = f a -> f (t a -> t a)
329					let map_cons = map::<ClonableFnBrand, F, _, _>(cons);
330					// f: a -> f b
331					// head: a
332					// f head: f b
333					let f_head = f(head);
334					// traverse: (a -> f b) -> t a -> f (t b)
335					// f: a -> f b
336					// traverse f: t a -> f (t b)
337					let traverse_f = traverse::<ClonableFnBrand, Self, F, _, _>(f.clone());
338					// traverse f: t a -> f (t b)
339					// tail: t a
340					// (traverse f) tail: f (t b)
341					let traverse_f_tail = traverse_f(tail);
342					// map cons: f a -> f (t a -> t a)
343					// f head: f b
344					// (map cons) (f head): f (t b -> t b)
345					let map_cons_f_head = map_cons(f_head);
346					// apply: f (a -> b) -> f a -> f b
347					// (map cons) (f head): f (t b -> t b)
348					// apply ((map cons) (f head)): f (t b) -> f (t b)
349					let apply_map_cons_f_head = apply::<ClonableFnBrand, F, _, _>(map_cons_f_head);
350					// apply ((map cons) (f head)): f (t b) -> f (t b)
351					// (traverse f) tail: f (t b)
352					// apply ((map cons) (f head)) ((traverse f) tail): f (t b)
353					apply_map_cons_f_head(traverse_f_tail)
354				}
355			}
356		})
357	}
358}