pub mod r#async;
pub mod blocking;
use core::{future::Future, ops::ControlFlow};
use crate::{higher_ranked_trait, higher_ranked_type};
// Goal: code using the module shouldn't care if the underlying environment is async or not.
// That is the API should allow yielding without forcing it.
//
// Escaping the effect wrapper requires knowing the concrete context or transforming in the more
// general form which is a Future.
// Async operations cannot be made blocking without issues.
//
// Async and blocking can perform loops. In async the loop will yield between iterations.
// The effective value becomes the loop context. This operation can encode arbitrary folds which
// gives a fully powerful loop construct. The callback effective is allowed to reference the
// context, but the returned value is not.
//
// Async and blocking can perform maps. This is a blocking transform of the value from one form to
// another.
//
// A map that returns an effective for the callback is a then.
//
// The special operation is as_ctx which allows a effective value to be referenced temporarily
// during the operation. This is basically a loop that happens onces.
//
// All effectives can be converted to the effect's erased effective.
//
// An effective can be made from a value.
//
// An effective can be made from a future.
//
// Multiple effectives can be joined together.
//
// E::join((
// || A,
// || B
// ))
pub trait Effect:
Join<Effect = Self> + TryJoin<Effect = Self> + Send + Sync + Sized + 'static
{
type Erased<T: Send + Sync>: ErasedHrt<T, Self>;
type Ready<'a, T: Send + Sync + 'a>: Effective<'a, Output = T, Effect = Self>;
fn ready<'a, T: Send + Sync + 'a>(value: T) -> Self::Ready<'a, T>;
type FromFuture<'a, F: Send + Sync + 'a>: Effective<'a, Output = F::Output, Effect = Self>
where
F: Future,
F::Output: Send + Sync + 'a;
fn from_future<'a, F: Send + Sync + 'a>(future: F) -> Self::FromFuture<'a, F>
where
F: Future,
F::Output: Send + Sync + 'a;
}
pub trait ErasedForLt<'a, T: Send + Sync + 'a, E: Effect, Bound: '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 type ErasedEffective<'lt, Output, E> =
<<E as Effect>::Erased<Output> as ErasedForLt<'lt, Output, E, &'lt Output>>::T;
pub trait Effective<'lt>: Send + Sync + 'lt {
fn into_erased(self) -> ErasedEffective<'lt, Self::Output, Self::Effect>;
/// The effect the effective belongs to.
type Effect: Effect;
/// The type of the effective's output value.
type Output: Send + Sync + 'lt;
/// Future that resolves to the same value as the effective.
type IntoFuture: Send + Sync + Future<Output = Self::Output>;
/// 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 Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
'a,
Output = T,
Effect = Self::Effect,
>
where
F: FnOnce(Self::Output) -> T,
'lt: 'a;
fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
where
F: FnOnce(Self::Output) -> T,
'lt: 'a;
type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
'a,
Output = T,
Effect = Self::Effect,
>
where
F: FnOnce(Self::Output) -> V,
V: Effective<'a, Output = T, Effect = Self::Effect>;
fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
self,
cb: F,
) -> Self::Then<'a, T, V, F>
where
F: FnOnce(Self::Output) -> V,
V: Effective<'a, Output = T, Effect = Self::Effect>;
type AsCtx<'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>,
'lt: 'a;
fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
where
F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>,
'lt: 'a;
}
pub trait Join {
type Effect: Effect;
type Two<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a>: Effective<
'a,
Output = (T0::Output, T1::Output),
Effect = Self::Effect,
>
where
T0: Effective<'a, Effect = Self::Effect>,
T1: Effective<'a, Effect = Self::Effect>;
type Three<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a>: Effective<
'a,
Output = (T0::Output, T1::Output, T2::Output),
Effect = Self::Effect,
>
where
T0: Effective<'a, Effect = Self::Effect>,
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),
) -> Self::Two<'a, T0, T1>
where
T0: Effective<'a, Effect = Self::Effect>,
T1: Effective<'a, Effect = Self::Effect>,
F0: FnOnce() -> T0,
F1: FnOnce() -> T1;
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),
) -> 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;
}
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>
where
V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
V1: Effective<'a, Output = Result<T1, 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>,
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>;
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>
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;
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>
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;
}