1use crate::Fx;
2use dyn_clone::{DynClone, clone_trait_object};
3
4impl<'f, S: Clone, V: Clone> Fx<'f, S, V> {
5 pub fn via<T, U, H>(self, h: H) -> Fx<'f, T, U>
6 where
7 T: Clone,
8 U: Clone,
9 H: Into<Handler<'f, S, T, V, U>>,
10 {
11 h.into().handle(self)
12 }
13}
14
15impl<'f, A: Clone, B: Clone, U: Clone, V: Clone> Handler<'f, A, B, U, V> {
16 pub fn on_left<S: Clone>(self) -> Handler<'f, (A, S), (B, S), U, V> {
17 Handler::new(move |e| e.and_swap().via(self.clone().on_right()).and_swap())
18 }
19
20 pub fn on_right<S: Clone>(self) -> Handler<'f, (S, A), (S, B), U, V> {
21 Handler::new(move |e| e.and_nest().via(self.clone().on_value()).and_flat())
22 }
23
24 pub fn on_value<S: Clone>(self) -> Handler<'f, S, S, Fx<'f, A, U>, Fx<'f, B, V>> {
25 Handler::new(move |e: Fx<'f, S, Fx<'f, A, U>>| {
26 e.flat_map(|i: Fx<'f, A, U>| Fx::func(move |h: Self| h.handle(i.clone())))
27 .and_swap()
28 .provide_left(self.clone())
29 })
30 }
31}
32
33impl<'f, A: Clone, B: Clone, U: Clone, V: Clone> Handler<'f, A, B, U, V> {
34 pub fn new<F>(f: F) -> Self
35 where
36 F: FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + Clone + 'f,
37 {
38 Self(Box::new(f))
39 }
40
41 pub fn handle(self, e: Fx<'f, A, U>) -> Fx<'f, B, V> {
42 self.0(e)
43 }
44
45 pub fn clone_boxed(&self) -> Box<dyn FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + 'f> {
46 self.0.clone()
47 }
48
49 pub fn contra_map<S, T, H>(self, h: H) -> Handler<'f, S, B, T, V>
50 where
51 H: FnOnce(Fx<'f, S, T>) -> Fx<'f, A, U> + Clone + 'f,
52 S: Clone,
53 T: Clone,
54 {
55 Handler::new(|e| self.handle(h(e)))
56 }
57
58 pub fn map<S, T, H>(self, h: H) -> Handler<'f, A, S, U, T>
59 where
60 H: FnOnce(Fx<'f, B, V>) -> Fx<'f, S, T> + Clone + 'f,
61 S: Clone,
62 T: Clone,
63 {
64 Handler::new(|e| h(self.handle(e)))
65 }
66}
67
68#[derive(Clone)]
69pub struct Handler<'f, A: Clone, B: Clone, U: Clone, V: Clone>(
70 Box<dyn HandlerFn<'f, A, B, U, V> + 'f>,
71);
72
73clone_trait_object!(<'f, A: Clone, B: Clone, U:Clone, V:Clone> HandlerFn<'f, A, B, U, V>);
74trait HandlerFn<'f, A, B, U, V>: DynClone + FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + 'f
75where
76 V: Clone + 'f,
77 U: Clone + 'f,
78 A: Clone + 'f,
79 B: Clone + 'f,
80{
81}
82impl<'f, A, B, U, V, F> HandlerFn<'f, A, B, U, V> for F
83where
84 F: FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + Clone + 'f,
85 V: Clone + 'f,
86 U: Clone + 'f,
87 A: Clone + 'f,
88 B: Clone + 'f,
89{
90}
91
92impl<'f, A, B, U, V, F> From<F> for Handler<'f, A, B, U, V>
93where
94 F: FnOnce(Fx<'f, A, U>) -> Fx<'f, B, V> + Clone + 'f,
95 V: Clone + 'f,
96 U: Clone + 'f,
97 A: Clone + 'f,
98 B: Clone + 'f,
99{
100 fn from(value: F) -> Self {
101 Handler::new(value)
102 }
103}
104
105impl<'f, A, B, U, V> From<Handler<'f, A, B, U, V>> for Box<dyn HandlerFn<'f, A, B, U, V> + 'f>
106where
107 V: Clone + 'f,
108 U: Clone + 'f,
109 A: Clone + 'f,
110 B: Clone + 'f,
111{
112 fn from(value: Handler<'f, A, B, U, V>) -> Self {
113 value.0
114 }
115}