1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//!
//! Foldable implementations and tests
//!
//!
use crate::Foldable::*;

impl <A, B> FoldableB<B> for Vec<A> {
  fn fold_right<F>(&self, z: B, f: F) -> B where F: Fn(&Self::A, B) -> B {
    let mut r: B = z;
    for x in self.iter().rev() {
      r = f(x, r);
    }
    r
  }
  fn fold_left<F>(&self, z: B, f: F) -> B where F: Fn(B, &Self::A) -> B {
    self.iter().fold(z, f)
  }
}

impl <'r,A: 'r> FoldableA<'r, A> for Vec<A> {
  fn fold<F>(&'r self, z: A, f: F) -> A where F: FnMut(A, &A) -> A {
    self.iter().fold(z, f)
  }
  fn all<F>(&'r self, f: F) -> bool where F: Fn(&A) -> bool {
    self.iter().all(f)
  }
  fn any<F>(&'r self, f: F) -> bool where F: Fn(&A) -> bool {
    self.iter().any(f)
  }
  fn filter<F>(&'r self, f: F) -> Self::M where F: Fn(&A) -> bool {
    self.iter().filter(|a| f(a)).collect()
  }
  fn find<F>(&'r self, f: F) -> Option<&A> where F: Fn(&A) -> bool {
    self.iter().find(|a| f(a))
  }
  fn is_empty(&'r self) -> bool { self.is_empty() }
}

impl <'r,A: 'r> FoldableS<'r, A> for Option<A> {
  fn fold<F>(&'r self, z: A, f: F) -> A where F: Fn(&A) -> A {
    match self {
      Some(v) => f(v),
      None => z,
    }
  }
  fn all<F>(&'r self, f: F) -> bool where F: Fn(&A) -> bool {
    self.iter().all(f)
  }
  fn any<F>(&'r self, f: F) -> bool where F: Fn(&A) -> bool {
    self.iter().any(f)
  }
  fn filter<F>(&'r self, f: F) -> Self::M where F: Fn(&A) -> bool {
    self.iter().find(|a| f(a))
  }
  fn find<F>(&'r self, f: F) -> Option<&A> where F: Fn(&A) -> bool {
    self.iter().find(|a| f(a))
  }
  fn is_empty(&'r self) -> bool { self.is_none() }
}

#[cfg(test)]
mod test {
  use crate::Foldable::*;

  #[test]
  fn vec_filter() {
    let v1 = vec![1,2,3,4];
    assert_eq!(vec![&2,&4], v1.filter(|&a| a%2==0))
  }

  #[test]
  fn option_filter_negative() {
    let v1 = Option::Some(7);
    assert_eq!(Option::None, v1.filter(|&a| a > 10));
  }

  #[test]
  fn option_filter_positive() {
    let v1 = Option::Some(7);
    assert_eq!(Option::Some(7), v1.filter(|&a| a < 10));
  }

  #[test]
  fn vec_filter_then_fold_left() {
    let v1 = vec![1,2,3,4];
    assert_eq!(6, v1.filter(|&a| a%2==0).fold_left(0, |b,&a| a + b));
  }

  #[test]
  fn vec_filter_then_fold_right() {
    let v1 = vec![1,2,3,4];
    assert_eq!(6, v1.filter(|&a| a%2==0).fold_right(0, |&a,b| a + b));
  }

  #[test]
  fn vec_concat() {
    let v1 = vec![(0.1f64 * 1000f64),(0.2f64 * 1000f64)];
    assert_eq!(0.3f64, (v1.concat() / 1000f64));
  }

}