1use crate::stack::Stack;
2use crate::StackError;
3use rust_fp_categories::*;
4use std::rc::Rc;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum List<A> {
8 Nil,
9 Cons { head: A, tail: Rc<List<A>> },
10}
11
12impl<A: Clone> From<Vec<A>> for List<A> {
13 fn from(vec: Vec<A>) -> Self {
14 vec.iter()
15 .rev()
16 .fold(List::empty(), |acc, e| acc.cons(e.clone()))
17 }
18}
19
20impl<A: Clone> Into<Vec<A>> for List<A> {
21 fn into(self) -> Vec<A> {
22 self.fold_left(vec![], |mut acc, h| {
23 acc.push(h.clone());
24 acc
25 })
26 }
27}
28
29impl<A: Clone> List<A> {
30 pub fn drop(self, n: u32) -> Self {
31 if n == 0 {
32 self
33 } else {
34 match self {
35 List::Nil => List::Nil,
36 List::Cons { tail: t, .. } => Rc::try_unwrap(t).unwrap_or(List::Nil).drop(n - 1),
37 }
38 }
39 }
40
41 pub fn reverse(&self) -> Self {
42 self.fold_left(List::empty(), |acc, h| acc.cons(h.clone()))
43 }
44}
45
46impl<A> Empty for List<A> {
49 fn empty() -> List<A> {
50 List::Nil
51 }
52 fn is_empty(&self) -> bool {
53 match self {
54 &List::Nil => true,
55 _ => false,
56 }
57 }
58}
59
60impl<A> Semigroup for List<A> {
61 fn combine(self, other: Self) -> Self {
62 match self {
63 List::Nil => other,
64 List::Cons { head: h, tail: t } => List::Cons {
65 head: h,
66 tail: Rc::new(Rc::try_unwrap(t).unwrap_or(List::Nil).combine(other)),
67 },
68 }
69 }
70}
71
72impl<A> Monoid for List<A> {}
73
74impl<A: Clone> Functor for List<A> {
77 type Elm = A;
78 type M<U> = List<U>;
79
80 fn fmap<B, F>(self, f: F) -> List<B>
81 where
82 F: Fn(&A) -> B,
83 List<B>: Stack<B>,
84 {
85 if self.is_empty() {
86 List::Nil
87 } else {
88 self.fold_right(List::<B>::empty(), |v, acc| acc.cons(f(&v)))
89 }
90 }
91}
92
93impl<A> Pure for List<A> {
96 type Elm = A;
97 type M<U> = List<U>;
98
99 fn pure(value: A) -> List<A> {
100 List::empty().cons(value)
101 }
102
103 fn unit() -> Self::M<()> {
104 List::empty().cons(())
105 }
106}
107
108impl<A> Apply for List<A> {
109 type Elm = A;
110 type M<U> = List<U>;
111
112 fn ap<B, F>(self, fs: Self::M<F>) -> Self::M<B>
113 where
114 F: Fn(&A) -> B,
115 List<B>: Stack<B>,
116 {
117 if self.is_empty() {
118 List::Nil
119 } else {
120 let mut result: List<B> = List::empty();
121 let mut cur1: &List<A> = &self;
122 let mut cur2: &List<F> = &fs;
123 while let List::Cons { ref head, ref tail } = *cur1 {
124 if let List::Cons {
125 head: ref hf,
126 tail: ref tf,
127 } = *cur2
128 {
129 result = result.cons((*hf)(head));
130 cur1 = tail;
131 cur2 = tf;
132 }
133 }
134 result
135 }
136 }
137}
138
139impl<A> Applicative for List<A> {}
140
141impl<A: Clone> Bind for List<A> {
144 type Elm = A;
145 type M<U> = List<U>;
146
147 fn bind<B, F>(self, f: F) -> List<B>
148 where
149 F: Fn(&A) -> List<B>,
150 {
151 if self.is_empty() {
152 List::Nil
153 } else {
154 self.fold_left(List::<B>::empty(), |acc, v| acc.combine(f(&v)))
155 }
156 }
157}
158
159impl<A: Clone> Monad for List<A> {}
160
161impl<A: Clone> Foldable for List<A> {
164 type Elm = A;
165
166 fn fold_left<B, F>(&self, b: B, f: F) -> B
167 where
168 F: Fn(B, &Self::Elm) -> B,
169 {
170 match self {
171 &List::Nil => b,
172 &List::Cons { ref head, ref tail } => tail.fold_left(f(b, head), f),
173 }
174 }
175
176 fn fold_right<B, F>(&self, b: B, f: F) -> B
177 where
178 F: Fn(&Self::Elm, B) -> B,
179 {
180 self.reverse().fold_left(b, |b, a| f(a, b))
181 }
182}
183
184impl<A> Stack<A> for List<A> {
185 fn cons(self, value: A) -> Self {
186 List::Cons {
187 head: value,
188 tail: Rc::new(self),
189 }
190 }
191
192 fn head(&self) -> Result<&A, StackError> {
193 match self {
194 &List::Nil => Err(StackError::NoSuchElementError),
195 &List::Cons {
196 head: ref value, ..
197 } => Ok(value),
198 }
199 }
200
201 fn tail(&self) -> Rc<Self> {
202 match self {
203 List::Nil => Rc::new(List::Nil),
204 List::Cons { tail, .. } => Rc::clone(tail),
205 }
206 }
207
208 fn size(&self) -> usize {
209 match self {
210 &List::Nil => 0,
211 &List::Cons { ref tail, .. } => 1 + tail.size(),
212 }
213 }
214
215 fn update(self, index: u32, new_value: A) -> Result<Self, StackError>
216 where
217 Self: Sized,
218 {
219 match self {
220 List::Nil => Err(StackError::IndexOutOfRangeError),
221 List::Cons {
222 head: value,
223 tail: tail_arc,
224 } => match index {
225 0 => {
226 let t: List<A> =
227 Rc::try_unwrap(tail_arc).map_err(|_| StackError::RcUnwrapError)?;
228 Ok(t.cons(new_value))
229 }
230 _ => {
231 let t: List<A> =
232 Rc::try_unwrap(tail_arc).map_err(|_| StackError::RcUnwrapError)?;
233 let updated_tail: List<A> = t.update(index - 1, new_value)?;
234 Ok(updated_tail.cons(value))
235 }
236 },
237 }
238 }
239
240 fn get(&self, index: u32) -> Result<&A, StackError> {
241 match self {
242 &List::Nil => Err(StackError::NoSuchElementError),
243 &List::Cons {
244 head: ref value,
245 tail: ref tail_arc,
246 } => match index {
247 0 => Ok(value),
248 _ => tail_arc.get(index - 1),
249 },
250 }
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use crate::list::List;
257 use crate::stack::StackError;
258 use crate::Stack;
259 use rust_fp_categories::Bind;
260 use rust_fp_categories::Empty;
261 use rust_fp_categories::Functor;
262 use rust_fp_categories::Semigroup;
263
264 #[test]
265 fn test_from_vec_to_vec() -> Result<(), StackError> {
266 let v1 = vec![1, 2, 3];
267 let expected1 = v1.clone();
268 let l1 = List::from(v1);
269 let v2: Vec<i32> = l1.into();
270 assert_eq!(v2, expected1);
271 Ok(())
272 }
273
274 #[test]
275 fn test_empty_cons() -> Result<(), StackError> {
276 let list1 = List::empty().cons(1);
277 assert_eq!(*list1.head()?, 1);
278 assert_eq!(*list1.tail(), List::empty());
279 Ok(())
280 }
281
282 #[test]
283 fn test_is_empty() -> Result<(), StackError> {
284 let list1 = List::empty().cons(1);
285 assert_eq!(list1.is_empty(), false);
286 assert_eq!(List::<i32>::empty().is_empty(), true);
287 Ok(())
288 }
289
290 #[test]
291 fn test_combine() -> Result<(), StackError> {
292 let list1 = List::empty().cons(1);
293 let list2 = List::empty().cons(1);
294 let list3 = list1.combine(list2);
295 let vec1: Vec<i32> = list3.into();
296 assert_eq!(vec1, vec![1, 1]);
297 Ok(())
298 }
299
300 #[test]
301 fn test_fmap() -> Result<(), StackError> {
302 let list1: List<i32> = List::from(vec![1, 2, 3, 4, 5]);
303 let list2: List<i32> = list1.fmap(|v| v * 2);
304 let vec1: Vec<i32> = list2.into();
305 assert_eq!(vec1, vec![2, 4, 6, 8, 10]);
306 Ok(())
307 }
308
309 #[test]
310 fn test_bind() -> Result<(), StackError> {
311 let list1: List<i32> = List::from(vec![1, 2, 3, 4, 5]);
312 let list2 = list1.clone();
313 let list3 = list1.bind(|_| List::<i32>::empty());
314 let vec1: Vec<i32> = list3.into();
315 assert_eq!(vec1, Vec::<i32>::empty());
316 let list4 = list2.bind(|v| List::<i32>::empty().cons(*v * 2));
317 let vec2: Vec<i32> = list4.into();
318 assert_eq!(vec2, vec![2, 4, 6, 8, 10]);
319 Ok(())
320 }
321
322 #[test]
323 fn test_head_tail() -> Result<(), StackError> {
324 let list1: List<i32> = List::from(vec![1, 2, 3, 4, 5]);
325 let head = list1.head()?;
326 let tail = list1.tail();
327 assert_eq!(*head, 1);
328 assert_eq!(*tail.as_ref(), List::from(vec![2, 3, 4, 5]));
329 let vec1: Vec<i32> = tail.as_ref().clone().into();
330 assert_eq!(vec1, vec![2, 3, 4, 5]);
331 Ok(())
332 }
333
334 #[test]
335 fn test_get() -> Result<(), StackError> {
336 let list1: List<i32> = List::empty().cons(5).cons(4).cons(3).cons(2).cons(1);
337 let chr = list1.get((list1.size() - 1) as u32)?;
338 assert_eq!(*chr, 5);
339 Ok(())
340 }
341
342 #[test]
343 fn test_eq() -> Result<(), StackError> {
344 let list1: List<i32> = List::from(vec![1, 2, 3, 4, 5]);
345 let list2: List<i32> = List::from(vec![2, 2, 3, 4, 5]);
346 assert_ne!(list1, list2);
347 assert_ne!(*list1.head()?, *list2.head()?);
348 assert_eq!(list1.tail(), list2.tail());
349 Ok(())
350 }
351}