1use crate::{Ability, Fx, Handler, State};
2
3pub type FoldAbility<'f, I, S, O, Acc> = Ability<'f, I, (Acc, S), O>;
4
5pub type FoldHandler<'f, I, S, O, V, Acc> =
6 Handler<'f, (FoldAbility<'f, I, S, O, Acc>, (Acc, S)), S, V, (Acc, V)>;
7
8impl<'f, I, S, O> FoldAbility<'f, I, S, O, Vec<O>>
9where
10 O: Clone,
11 S: Clone + 'f,
12 I: Clone + 'f,
13{
14 pub fn fold_to_vec<V>(self) -> FoldHandler<'f, I, S, O, V, Vec<O>>
15 where
16 V: Clone,
17 {
18 self.fold(Vec::new(), |mut vec, o| {
19 Fx::value({
20 vec.push(o);
21 vec
22 })
23 })
24 }
25}
26
27impl<'f, I, S, O> FoldAbility<'f, I, S, O, Option<O>>
28where
29 O: Clone,
30 S: Clone + 'f,
31 I: Clone + 'f,
32{
33 pub fn fold_to_option<V>(self) -> FoldHandler<'f, I, S, O, V, Option<O>>
34 where
35 V: Clone,
36 {
37 self.fold(None, |_opt, o| Fx::value(Some(o)))
38 }
39
40 pub fn fold_to_some<V>(self) -> Handler<'f, (Self, (Option<O>, S)), S, V, (O, V)>
41 where
42 V: Clone,
43 {
44 self.fold_to_option()
45 .map(|f: Fx<'f, S, (Option<O>, V)>| f.map(|(o, v)| (o.unwrap(), v)))
46 }
47}
48
49impl<'f, I, S, O, Acc> FoldAbility<'f, I, S, O, Acc>
50where
51 O: Clone,
52 S: Clone + 'f,
53 I: Clone + 'f,
54 Acc: Clone + 'f,
55{
56 pub fn fold<V, F>(self, acc: Acc, of: F) -> FoldHandler<'f, I, S, O, V, Acc>
57 where
58 V: Clone + 'f,
59 F: (FnOnce(Acc, O) -> Fx<'f, S, Acc>) + Clone + 'f,
60 {
61 Handler::new(|e| {
62 let ab = self.hmap(|f| {
63 f.map_m(|o| {
64 let o1 = o.clone();
65 State::update(|(a, s): (Acc, S)| of(a, o1).map(|a| (a, s)))
66 .contra_map::<(Acc, S), _, _>(|(o, s)| ((o, s.clone()), s), |_, (os, _)| os)
67 .map(|_| o)
68 })
69 });
70
71 e.map_m(|v| State::get().map(|(_ab, (a, _s)): (Self, (Acc, S))| (a, v)))
72 .provide_left(ab)
73 .provide_left(acc)
74 })
75 }
76}