1use std::convert::identity as id;
2
3use tinyvec::ArrayVec;
4
5use crate::prelude::*;
6
7pub mod hkt {
9 use super::*;
10
11 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#[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#[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
134pub 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}