fx_rs/core/
fold.rs

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}