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