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}