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}