1pub trait EnvIO {
2 type Out;
3
4 fn run(self) -> Self::Out;
5
6 fn flat_map<OutEnv, F>(self, f: F) -> FlatMap<Self, F>
7 where Self: Sized, OutEnv: EnvIO, F: Fn(Self::Out) -> OutEnv {
8 FlatMap { envio: self, f }
9 }
10}
11
12pub struct Effect<Out, F: Fn() -> Out> {
13 effect: F
14}
15
16impl<Out0, F: Fn() -> Out0> EnvIO for Effect<Out0, F> {
17 type Out = Out0;
18
19 fn run(self) -> Self::Out {
20 (self.effect)()
21 }
22}
23
24pub struct FlatMap<Env, F> {
25 envio: Env,
26 f: F
27}
28
29impl<Env: EnvIO, OutEnv: EnvIO, F> EnvIO for FlatMap<Env, F> where F: Fn(Env::Out) -> OutEnv {
30 type Out = OutEnv::Out;
31
32 fn run(self) -> OutEnv::Out {
33 (self.f)(self.envio.run()).run()
34 }
35}
36
37pub trait IntoEnvIO {
38 type Out;
39
40 type IntoEnv: EnvIO<Out=Self::Out>;
41
42 fn effect(self) -> Self::IntoEnv;
43}
44
45impl<T, F: Fn() -> T> IntoEnvIO for F {
46 type Out = T;
47 type IntoEnv = Effect<T, F>;
48
49 fn effect(self) -> Self::IntoEnv {
50 Effect { effect: self }
51 }
52}
53
54#[macro_export]
55macro_rules! eff {
56 ($e:expr) => {
57 (move || $e).effect()
58 }
59}