Diffstat (limited to 'src/effect.rs')
-rw-r--r--src/effect.rs251
1 files changed, 172 insertions, 79 deletions
diff --git a/src/effect.rs b/src/effect.rs
index e8891ad..0c85769 100644
--- a/src/effect.rs
+++ b/src/effect.rs
@@ -58,22 +58,19 @@ pub trait Effect:
F::Output: Send + Sync + 'a;
}
-pub trait ErasedForLt<'a, T: Send + Sync + 'a, E: Effect, Bound: 'a> {
+pub trait ErasedForLt<'a, T: Send + Sync + 'a, E: Effect, Bound: 'a, O: 'a> {
type T: Effective<'a, Output = T, Effect = E>;
}
-pub trait ErasedHrt<T: Send + Sync, E: Effect>: for<'a> ErasedForLt<'a, T, E, &'a T> {}
-
-impl<T: Send + Sync, E: Effect, U> ErasedHrt<T, E> for U where
- U: for<'a> ErasedForLt<'a, T, E, &'a T>
-{
+pub trait ErasedHrt<T: Send + Sync, E: Effect> {
+ type T<B>: for<'a> ErasedForLt<'a, T, E, &'a (T, B), B>;
}
-pub type ErasedEffective<'lt, Output, E> =
- <<E as Effect>::Erased<Output> as ErasedForLt<'lt, Output, E, &'lt Output>>::T;
+pub type ErasedEffective<'lt, Output, E, B = ()> =
+ <<<E as Effect>::Erased<Output> as ErasedHrt<Output, E>>::T<B> as ErasedForLt<'lt, Output, E, &'lt (Output, B), B>>::T;
pub trait Effective<'lt>: Send + Sync + 'lt {
- fn into_erased(self) -> ErasedEffective<'lt, Self::Output, Self::Effect>;
+ fn into_erased<B>(self) -> ErasedEffective<'lt, Self::Output, Self::Effect, B>;
/// The effect the effective belongs to.
type Effect: Effect;
@@ -87,18 +84,19 @@ pub trait Effective<'lt>: Send + Sync + 'lt {
/// Convert the effective into a general future for use in async.
fn into_future(self) -> Self::IntoFuture;
- // /// Effective performing a loop.
- // type Loop<T, V, F>: Effective<Output = (Self::Output, T), Effect = Self::Effect>
- // where
- // F: MutFnOnceHrt<Self::Output, T, Self::Effect>;
- //
- // /// Perform a loop with the effective value as context.
- // ///
- // /// When the callback returns break then the loop will end and the effective
- // /// will resolve to the break value and the context.
- // fn r#loop<T, V, F>(self, cb: F) -> Self::Loop<T, V, F>
- // where
- // F: MutFnOnceHrt<Self::Output, T, Self::Effect>;
+ type Loop<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
+ 'a,
+ Output = (Self::Output, T),
+ Effect = Self::Effect,
+ >
+ where
+ F: for<'b> FnMut(&'b mut Self::Output) -> ErasedEffective<'b, ControlFlow<T>, Self::Effect, (&'b mut Self::Output, &'ctx ())>,
+ 'lt: 'a;
+
+ fn r#loop<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Loop<'ctx, 'a, T, F>
+ where
+ F: for<'b> FnMut(&'b mut Self::Output) -> ErasedEffective<'b, ControlFlow<T>, Self::Effect, (&'b mut Self::Output, &'ctx ())>,
+ 'lt: 'a;
type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
'a,
@@ -121,7 +119,8 @@ pub trait Effective<'lt>: Send + Sync + 'lt {
>
where
F: FnOnce(Self::Output) -> V,
- V: Effective<'a, Output = T, Effect = Self::Effect>;
+ V: Effective<'a, Output = T, Effect = Self::Effect>,
+ 'lt: 'a;
fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
self,
@@ -129,23 +128,40 @@ pub trait Effective<'lt>: Send + Sync + 'lt {
) -> Self::Then<'a, T, V, F>
where
F: FnOnce(Self::Output) -> V,
- V: Effective<'a, Output = T, Effect = Self::Effect>;
+ V: Effective<'a, Output = T, Effect = Self::Effect>,
+ 'lt: 'a;
- type AsCtx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
+ type AsCtx<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
'a,
Output = (Self::Output, T),
Effect = Self::Effect,
>
where
- F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>,
+ F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect, (&'b mut Self::Output, &'ctx ())>,
'lt: 'a;
- fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
+ fn as_ctx<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'ctx, 'a, T, F>
where
- F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>,
+ F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect, (&'b mut Self::Output, &'ctx ())>,
'lt: 'a;
}
+pub trait TryEffective<'lt>: Effective<'lt, Output = Result<Self::Ok, Self::Err>> {
+ type Ok: Send + Sync + 'lt;
+ type Err: Send + Sync + 'lt;
+}
+
+impl<'lt, T, Ok, Err> TryEffective<'lt> for T
+where
+ T: Effective<'lt, Output = Result<Ok, Err>>,
+ Ok: Send + Sync + 'lt,
+ Err: Send + Sync + 'lt,
+{
+ type Ok = Ok;
+
+ type Err = Err;
+}
+
pub trait Join {
type Effect: Effect;
@@ -168,96 +184,173 @@ pub trait Join {
T1: Effective<'a, Effect = Self::Effect>,
T2: Effective<'a, Effect = Self::Effect>;
- fn two<
- 'a,
- T0: Send + Sync + 'a,
- T1: Send + Sync + 'a,
- F0: Send + Sync + 'a,
- F1: Send + Sync + 'a,
- >(
- cb: (F0, F1),
+ fn two<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a>(
+ effectives: (T0, T1),
) -> Self::Two<'a, T0, T1>
where
T0: Effective<'a, Effect = Self::Effect>,
- T1: Effective<'a, Effect = Self::Effect>,
- F0: FnOnce() -> T0,
- F1: FnOnce() -> T1;
+ T1: Effective<'a, Effect = Self::Effect>;
- fn three<
- 'a,
- T0: Send + Sync + 'a,
- T1: Send + Sync + 'a,
- T2: Send + Sync + 'a,
- F0: Send + Sync + 'a,
- F1: Send + Sync + 'a,
- F2: Send + Sync + 'a,
- >(
- effectives: (F0, F1, F2),
+ fn three<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a>(
+ effectives: (T0, T1, T2),
) -> Self::Three<'a, T0, T1, T2>
where
T0: Effective<'a, Effect = Self::Effect>,
T1: Effective<'a, Effect = Self::Effect>,
- T2: Effective<'a, Effect = Self::Effect>,
- F0: FnOnce() -> T0,
- F1: FnOnce() -> T1,
- F2: FnOnce() -> T2;
+ T2: Effective<'a, Effect = Self::Effect>;
}
pub trait TryJoin {
type Effect: Effect;
- type Two<'a, Err: Send + Sync + 'a, V0: Send + Sync + 'a, V1: Send + Sync + 'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a>: Effective<'a, Output = Result<(T0, T1), Err>, Effect = Self::Effect>
+ type Two<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a>: Effective<
+ 'a,
+ Output = Result<(T0::Ok, T1::Ok), T0::Err>,
+ Effect = Self::Effect,
+ >
where
- V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>;
+ T0: TryEffective<'a, Effect = Self::Effect>,
+ T1: TryEffective<'a, Err = T0::Err, Effect = Self::Effect>;
- type Three<'a, Err: Send + Sync + 'a, V0: Send + Sync + 'a, V1: Send + Sync + 'a, V2: Send + Sync + 'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a>: Effective<'a,
- Output = Result<(T0, T1, T2), Err>,
+ type Three<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a>: Effective<
+ 'a,
+ Output = Result<(T0::Ok, T1::Ok, T2::Ok), T0::Err>,
Effect = Self::Effect,
>
where
- V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
- V2: Effective<'a, Output = Result<T2, Err>, Effect = Self::Effect>;
+ T0: TryEffective<'a, Effect = Self::Effect>,
+ T1: TryEffective<'a, Err = T0::Err, Effect = Self::Effect>,
+ T2: TryEffective<'a, Err = T0::Err, Effect = Self::Effect>;
fn two<
'a,
- Err: Send + Sync + 'a,
T0: Send + Sync + 'a,
T1: Send + Sync + 'a,
- V0: Send + Sync + 'a,
- V1: Send + Sync + 'a,
F0: Send + Sync + 'a,
F1: Send + Sync + 'a,
>(
cb: (F0, F1),
- ) -> Self::Two<'a, Err, V0, V1, T0, T1>
+ ) -> Self::Two<'a, T0, T1>
where
- V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
- F0: FnOnce() -> V0,
- F1: FnOnce() -> V1;
+ T0: TryEffective<'a, Effect = Self::Effect>,
+ T1: TryEffective<'a, Err = T0::Err, Effect = Self::Effect>,
+ F0: FnOnce() -> T0,
+ F1: FnOnce() -> T1;
fn three<
'a,
- Err: Send + Sync + 'a,
T0: Send + Sync + 'a,
T1: Send + Sync + 'a,
T2: Send + Sync + 'a,
- V0: Send + Sync + 'a,
- V1: Send + Sync + 'a,
- V2: Send + Sync + 'a,
F0: Send + Sync + 'a,
F1: Send + Sync + 'a,
F2: Send + Sync + 'a,
>(
cb: (F0, F1, F2),
- ) -> Self::Three<'a, Err, V0, V1, V2, T0, T1, T2>
+ ) -> Self::Three<'a, T0, T1, T2>
where
- V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
- V2: Effective<'a, Output = Result<T2, Err>, Effect = Self::Effect>,
- F0: FnOnce() -> V0,
- F1: FnOnce() -> V1,
- F2: FnOnce() -> V2;
+ T0: TryEffective<'a, Effect = Self::Effect>,
+ T1: TryEffective<'a, Err = T0::Err, Effect = Self::Effect>,
+ T2: TryEffective<'a, Err = T0::Err, Effect = Self::Effect>,
+ F0: FnOnce() -> T0,
+ F1: FnOnce() -> T1,
+ F2: FnOnce() -> T2;
+}
+
+pub fn join<'lt, E: Effect, T: Joinable<'lt, E>>(x: T) -> T::Output {
+ x.join()
+}
+
+pub trait Joinable<'lt, E: Effect> {
+ type Output: Effective<'lt, Effect = E>;
+
+ fn join(self) -> Self::Output;
+}
+
+impl<'lt, E: Effect> Joinable<'lt, E> for () {
+ type Output = E::Ready<'lt, ()>;
+
+ fn join(self) -> Self::Output {
+ E::ready(())
+ }
+}
+
+impl<'lt, E: Effect, T0> Joinable<'lt, E> for (T0,)
+where
+ T0: Effective<'lt, Effect = E>,
+{
+ type Output = T0;
+
+ fn join(self) -> Self::Output {
+ self.0
+ }
+}
+
+impl<'lt, E: Effect, T0, T1> Joinable<'lt, E> for (T0, T1)
+where
+ T0: Effective<'lt, Effect = E>,
+ T1: Effective<'lt, Effect = E>,
+{
+ type Output = <E as Join>::Two<'lt, T0, T1>;
+
+ fn join(self) -> Self::Output {
+ <E as Join>::two(self)
+ }
+}
+
+impl<'lt, E: Effect, T0, T1, T2> Joinable<'lt, E> for (T0, T1, T2)
+where
+ T0: Effective<'lt, Effect = E>,
+ T1: Effective<'lt, Effect = E>,
+ T2: Effective<'lt, Effect = E>,
+{
+ type Output = <E as Join>::Three<'lt, T0, T1, T2>;
+
+ fn join(self) -> Self::Output {
+ <E as Join>::three(self)
+ }
+}
+
+pub fn try_join<'lt, E: Effect, T: TryJoinable<'lt, E>>(x: T) -> T::Output {
+ x.join()
+}
+
+pub trait TryJoinable<'lt, E: Effect> {
+ type Output: TryEffective<'lt, Effect = E>;
+
+ fn join(self) -> Self::Output;
+}
+
+impl<'lt, E: Effect> TryJoinable<'lt, E> for () {
+ type Output = E::Ready<'lt, Result<(), ()>>;
+
+ fn join(self) -> Self::Output {
+ E::ready(Ok(()))
+ }
+}
+
+impl<'lt, E: Effect, F0, T0> TryJoinable<'lt, E> for (F0,)
+where
+ F0: FnOnce() -> T0,
+ T0: TryEffective<'lt, Effect = E>,
+{
+ type Output = T0;
+
+ fn join(self) -> Self::Output {
+ self.0()
+ }
+}
+
+impl<'lt, E: Effect, F0, F1, T0, T1> TryJoinable<'lt, E> for (F0, F1)
+where
+ F0: FnOnce() -> T0 + Send + Sync + 'lt,
+ F1: FnOnce() -> T1 + Send + Sync + 'lt,
+ T0: TryEffective<'lt, Effect = E>,
+ T1: TryEffective<'lt, Err = T0::Err, Effect = E>,
+{
+ type Output = <E as TryJoin>::Two<'lt, T0, T1>;
+
+ fn join(self) -> Self::Output {
+ <E as TryJoin>::two(self)
+ }
}