naan/impls/
tinyvec.rs

1use std::convert::identity as id;
2
3use tinyvec::ArrayVec;
4
5use crate::prelude::*;
6
7/// Tinyvec HKTs
8pub mod hkt {
9  use super::*;
10
11  /// [`tinyvec::ArrayVec`] lifted to an HKT1
12  ///
13  /// (Kind `Type -> Type`)
14  pub struct ArrayVec<const N: usize>;
15  impl<const N: usize> HKT1 for ArrayVec<N> {
16    type T<A> = tinyvec::ArrayVec<[Option<A>; N]>;
17  }
18}
19
20impl<const N: usize, A> Functor<hkt::ArrayVec<N>, A> for ArrayVec<[Option<A>; N]> {
21  fn fmap<AB, B>(self, f: AB) -> ArrayVec<[Option<B>; N]>
22    where AB: F1<A, Ret = B>
23  {
24    self.into_iter().map(|a| a.fmap(|a| f.call(a))).collect()
25  }
26}
27
28impl<const N: usize, AB> Apply<hkt::ArrayVec<N>, AB> for ArrayVec<[Option<AB>; N]> {
29  fn apply_with<A, B, Cloner>(self,
30                              as_: ArrayVec<[Option<A>; N]>,
31                              clone: Cloner)
32                              -> ArrayVec<[Option<B>; N]>
33    where AB: F1<A, Ret = B>,
34          Cloner: for<'a> F1<&'a A, Ret = A>
35  {
36    self.into_iter()
37        .filter_map(|atob| atob)
38        .map(|atob| {
39          as_.iter()
40             .map(|a| {
41               a.as_ref()
42                .fmap(|a_ref| clone.call(a_ref))
43                .fmap(|a| atob.call(a))
44             })
45             .collect::<ArrayVec<[Option<B>; N]>>()
46        })
47        .flatten()
48        .collect()
49  }
50}
51
52impl<A, const N: usize> Applicative<hkt::ArrayVec<N>, A> for ArrayVec<[Option<A>; N]> {
53  fn pure(a: A) -> Self {
54    tinyvec::array_vec!(_ => Some(a))
55  }
56}
57
58impl<const N: usize, A> Alt<hkt::ArrayVec<N>, A> for ArrayVec<[Option<A>; N]> {
59  fn alt(mut self, mut b: Self) -> Self {
60    ArrayVec::append(&mut self, &mut b);
61    self
62  }
63}
64
65impl<A, const N: usize> Plus<hkt::ArrayVec<N>, A> for ArrayVec<[Option<A>; N]> {
66  fn empty() -> Self {
67    Default::default()
68  }
69}
70
71impl<A, const N: usize> Semigroup for ArrayVec<[Option<A>; N]> {
72  fn append(self, b: Self) -> Self {
73    self.alt(b)
74  }
75}
76
77impl<A, const N: usize> Monoid for ArrayVec<[Option<A>; N]> {
78  fn identity() -> Self {
79    Self::empty()
80  }
81}
82
83impl<A, const N: usize> Foldable<hkt::ArrayVec<N>, A> for ArrayVec<[Option<A>; N]> {
84  fn foldl<B, BAB>(self, f: BAB, b: B) -> B
85    where BAB: F2<B, A, Ret = B>
86  {
87    self.into_iter().filter_map(id).fold(b, |b, a| f.call(b, a))
88  }
89
90  fn foldr<B, ABB>(self, f: ABB, b: B) -> B
91    where ABB: F2<A, B, Ret = B>
92  {
93    self.into_iter()
94        .filter_map(id)
95        .rfold(b, |b, a| f.call(a, b))
96  }
97
98  fn foldl_ref<'a, B, BAB>(&'a self, f: BAB, b: B) -> B
99    where BAB: F2<B, &'a A, Ret = B>,
100          A: 'a
101  {
102    self.iter()
103        .filter_map(Option::as_ref)
104        .fold(b, |b, a| f.call(b, a))
105  }
106
107  fn foldr_ref<'a, B, ABB>(&'a self, f: ABB, b: B) -> B
108    where ABB: F2<&'a A, B, Ret = B>,
109          A: 'a
110  {
111    self.iter()
112        .filter_map(Option::as_ref)
113        .rfold(b, |b, a| f.call(a, b))
114  }
115}
116
117#[allow(non_camel_case_types)]
118type append<const N: usize, T> = fn(T, ArrayVec<[Option<T>; N]>) -> ArrayVec<[Option<T>; N]>;
119
120/// curried [`fn@append`] waiting for both arguments
121#[allow(non_camel_case_types)]
122pub type append0<const N: usize, T> = curry2::Curry2<append<N, T>,
123                                                     Nothing<T>,
124                                                     Nothing<ArrayVec<[Option<T>; N]>>,
125                                                     ArrayVec<[Option<T>; N]>>;
126
127/// curried [`fn@append`] that has a T and is waiting for the Vec to push it to
128#[allow(non_camel_case_types)]
129pub type append1<const N: usize, T> = curry2::Curry2<append<N, T>,
130                                                     Just<T>,
131                                                     Nothing<ArrayVec<[Option<T>; N]>>,
132                                                     ArrayVec<[Option<T>; N]>>;
133
134/// Append an element to a vec
135pub fn append<const N: usize, T>(t: T,
136                                 mut v: ArrayVec<[Option<T>; N]>)
137                                 -> ArrayVec<[Option<T>; N]> {
138  v.push(Some(t));
139  v
140}
141
142impl<A, B, const N: usize> Traversable<hkt::ArrayVec<N>, A, B, append1<N, B>>
143  for ArrayVec<[Option<A>; N]> where hkt::ArrayVec<N>: HKT1<T<B> = ArrayVec<[Option<B>; N]>>
144{
145  fn traversem1<Ap, AtoApOfB>(self, f: AtoApOfB) -> Ap::T<ArrayVec<[Option<B>; N]>>
146    where Ap: HKT1,
147          Self: Foldable<hkt::ArrayVec<N>, A>,
148          Ap::T<B>: Applicative<Ap, B> + ApplyOnce<Ap, B>,
149          Ap::T<append1<N, B>>: Applicative<Ap, append1<N, B>> + ApplyOnce<Ap, append1<N, B>>,
150          Ap::T<ArrayVec<[Option<B>; N]>>:
151            Applicative<Ap, ArrayVec<[Option<B>; N]>> + ApplyOnce<Ap, ArrayVec<[Option<B>; N]>>,
152          AtoApOfB: F1<A, Ret = Ap::T<B>>,
153          hkt::ArrayVec<N>: HKT1<T<A> = Self>
154  {
155    self.foldl(|ap, a| f.call(a).fmap((append as append<N, B>).curry()).apply1(ap),
156               Ap::T::pure(ArrayVec::<[Option<B>; N]>::identity()))
157  }
158
159  fn traversemm<Ap, AtoApOfB>(self, f: AtoApOfB) -> Ap::T<ArrayVec<[Option<B>; N]>>
160    where Ap: HKT1,
161          Self: Foldable<hkt::ArrayVec<N>, A>,
162          B: Clone,
163          Ap::T<B>: Applicative<Ap, B>,
164          Ap::T<append1<N, B>>: Applicative<Ap, append1<N, B>>,
165          Ap::T<ArrayVec<[Option<B>; N]>>: Applicative<Ap, ArrayVec<[Option<B>; N]>>,
166          AtoApOfB: F1<A, Ret = Ap::T<B>>,
167          hkt::ArrayVec<N>: HKT1<T<A> = Self>
168  {
169    self.foldl(|ap, a| f.call(a).fmap((append as append<N, B>).curry()).apply(ap),
170               Ap::T::pure(ArrayVec::<[Option<B>; N]>::identity()))
171  }
172}
173
174impl<A, const N: usize> Monad<hkt::ArrayVec<N>, A> for ArrayVec<[Option<A>; N]> {
175  fn bind<B, AMB>(self, f: AMB) -> ArrayVec<[Option<B>; N]>
176    where AMB: F1<A, Ret = ArrayVec<[Option<B>; N]>>
177  {
178    let mut out = ArrayVec::empty();
179
180    for i in self {
181      if let Some(i) = i {
182        ArrayVec::append(&mut out, &mut f.call(i));
183      }
184    }
185
186    out
187  }
188}
189
190#[cfg(test)]
191mod tests {
192  use super::*;
193
194  #[test]
195  fn tinyvec() {
196    type V = tinyvec::ArrayVec<[Option<u32>; 32]>;
197
198    let v = V::empty();
199    assert_eq!(v, V::default());
200
201    let v = v.append(V::pure(1)).append(V::pure(2)).append(V::pure(3));
202    assert_eq!(v, tinyvec::array_vec!(_ => Some(1), Some(2), Some(3)));
203
204    let sum = v.clone().foldl(|sum, n| sum + n, 0);
205    assert_eq!(sum, 6);
206
207    type R = Result<u32, ()>;
208    type RV = tinyvec::ArrayVec<[Option<R>; 32]>;
209
210    let rv = RV::empty().append(RV::pure(R::Ok(1)))
211                        .append(RV::pure(R::Ok(2)));
212    assert_eq!(rv.sequence::<crate::hkt::ResultOk<()>>(),
213               Result::<V, ()>::Ok(tinyvec::array_vec!(_ => Some(1), Some(2))));
214  }
215}