env_io/
lib.rs

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}