fx_rs/core/
fx.rs

1use crate::Fx;
2
3use super::State;
4
5impl<'f, V: Clone> Fx<'f, (), V> {
6    pub fn pure(value: V) -> Self {
7        Fx::immediate((), value)
8    }
9}
10
11impl<'f, S: Clone, V: Clone> Fx<'f, S, V> {
12    pub fn value(value: V) -> Self {
13        Fx::pending(|s: S| Fx::immediate(s, value))
14    }
15
16    pub fn func<F>(f: F) -> Self
17    where
18        F: FnOnce(S) -> V + Clone + 'f,
19    {
20        State::get().map(f)
21    }
22
23    pub fn map_m<U, F>(self, f: F) -> Fx<'f, S, U>
24    where
25        U: Clone,
26        F: FnOnce(V) -> Fx<'f, S, U> + Clone + 'f,
27    {
28        self.adapt(|s| s, |_s, s, v| f(v).contra_map(|_| s, |_s, s| s))
29    }
30
31    pub fn map<U, F>(self, f: F) -> Fx<'f, S, U>
32    where
33        U: Clone,
34        F: FnOnce(V) -> U + Clone + 'f,
35    {
36        self.map_m(|v| Fx::value(f(v)))
37    }
38
39    pub fn flat_map<R, U, F>(self, f: F) -> Fx<'f, (S, R), U>
40    where
41        U: Clone,
42        V: Clone,
43        R: Clone,
44        F: FnOnce(V) -> Fx<'f, R, U> + Clone + 'f,
45    {
46        self.adapt(
47            |(s, _r)| s,
48            |_sr, s, v| {
49                f(v).adapt(
50                    |(_s, r)| r,
51                    |_sr, r, u| Fx::value(u).contra_map(|_sr| (s, r), |_sr, sr| sr),
52                )
53            },
54        )
55    }
56
57    pub fn then<U>(self, e: Fx<'f, S, U>) -> Fx<'f, S, U>
58    where
59        U: Clone,
60    {
61        self.map_m(|_| e)
62    }
63
64    pub fn and_then<T, U>(self, e: Fx<'f, T, U>) -> Fx<'f, (S, T), U>
65    where
66        T: Clone,
67        U: Clone,
68    {
69        self.flat_map(|_| e)
70    }
71
72    pub fn contra_map<Outer, Getter, Setter>(
73        self,
74        getter: Getter,
75        setter: Setter,
76    ) -> Fx<'f, Outer, V>
77    where
78        Outer: Clone,
79        Getter: FnOnce(Outer) -> S + Clone + 'f,
80        Setter: FnOnce(Outer, S) -> Outer + Clone + 'f,
81    {
82        self.adapt(
83            |t: Outer| getter(t),
84            |t, s, v| Fx::immediate(setter(t, s), v),
85        )
86    }
87}