fp_library/types/
vec.rs

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