| -rw-r--r-- | src/effect.rs | 937 | ||||
| -rw-r--r-- | src/effect/blocking.rs | 164 | ||||
| -rw-r--r-- | src/lib.rs | 16 |
3 files changed, 305 insertions, 812 deletions
diff --git a/src/effect.rs b/src/effect.rs index dea709c..84b275b 100644 --- a/src/effect.rs +++ b/src/effect.rs @@ -1,860 +1,189 @@ -use core::{ - future::Future, - marker::PhantomData, - ops::ControlFlow, - pin::{pin, Pin}, - ptr, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, -}; - -use futures::FutureExt; -use pin_project::pin_project; - -use crate::{higher_ranked_trait, higher_ranked_type, hkt::Marker}; - -// higher_ranked_trait! { -// pub type class Effective['lt, E] for<'a> { -// type Bound = &'a (&'lt (), T, E); +pub mod blocking; + +use core::{future::Future, ops::ControlFlow}; + +// 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. // -// type T: { Adapters<'a, Effect = E, T = T> + Sized + 'a } -// where { -// 'lt: 'a, -// T: 'a, -// E: Effect, -// }; +// 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. // -// type HigherRanked: {} where { -// E: Effect, -// }; -// } -// } - -// fn do_thing<E: Effect>() -> ObjSafe<'static, i32, E> { -// E::ready(42).with(|x| { -// other::<E>(x).map(|x| x + 1).into() -// }).into() -// } +// 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. // -// fn other<E: Effect>(x: &i32) -> ObjSafe<'_, &i32, E> { -// E::ready(x).into() -// } - -// pub mod Effective { +// 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. // -pub trait Adapters<'lt>: Into<ObjSafe<'lt, Self::T, Self::Effect>> + 'lt { - type Effect: Effect; - type T: 'lt; +// 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 +// )) - type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T>: Adapters<'a, Effect = Self::Effect, T = T> - where - 'lt: 'a; +pub trait Effect: + Join<Effect = Self> + TryJoin<Effect = Self> + Send + Sync + Sized + 'static +{ + type Erased<T>: Effective<Output = T, Effect = Self>; - fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> - where - F: FnOnce(Self::T) -> R, - 'lt: 'a; + type Ready<T>: Effective<Output = T, Effect = Self>; - type AsCtxFor: HktFn<Self::Effect> + HktFnOwn<Self::Effect> + HktFnMut<Self::Effect>; + fn ready<T>(value: T) -> Self::Ready<T>; - fn as_ctx_for<'ctx, 'a, R: 'a, F: 'a>(self, f: F) -> ObjSafe<'a, (Self::T, R), Self::Effect> - where - F: for<'b> FnOnce( - &'b mut Self::T, - PhantomData<&'b &'ctx ()>, - ) -> (ObjSafe<'b, R, Self::Effect>, PhantomData<&'b &'ctx ()>); - - fn then<'ctx, 'a, R: 'a, F: 'a>( - self, - f: F, - ) -> <<Self::AsCtxFor as HktFnOwn<Self::Effect>>::T<Self::T, R, F, &'ctx ()> as ForLtFnOwn< - 'a, - Self::T, - R, - F, - &'a (Self::T, R, F, &'ctx ()), - &'ctx (), - Self::Effect, - >>::T + type FromFuture<F>: Effective<Output = F::Output, Effect = Self> where - F: for<'b> FnOnce( - Self::T, - PhantomData<&'b &'ctx ()>, - ) -> ObjSafe<'b, R, Self::Effect>; + F: Future; - fn r#loop<'ctx, 'a, R: 'a, F: 'a>(self, f: F) -> ObjSafe<'a, R, Self::Effect> + fn from_future<F>() -> Self::FromFuture<F> where - F: for<'b> FnMut(&'b mut Self::T) -> ObjSafe<'b, ControlFlow<R>, Self::Effect>; -} - -pub trait ForLt<'a, Output: 'a, B> { - type Effect: Effect; - - type T: Adapters<'a, Effect = Self::Effect, T = Output>; -} - -pub trait Hkt { - type Effect: Effect; - - type T<Output, B>: for<'a> ForLt<'a, Output, &'a (Output, B), Effect = Self::Effect>; -} - -pub trait ForLtFn<'a, Input: 'a, Output: 'a, F: 'a, B, O, E: Effect> -where - F: for<'b> FnOnce( - &'b mut Input, - PhantomData<&'b O>, - ) -> (ObjSafe<'b, Output, E>, PhantomData<&'b O>), -{ - type T: Adapters<'a, Effect = E, T = Output>; + F: Future; } -pub trait HktFn<E: Effect> { - type T<Input, Output, F: for<'b> FnOnce(&'b mut Input, PhantomData<&'b B>) -> (ObjSafe<'b, Output, E>, PhantomData<&'b B>), B>: for<'a> ForLtFn<'a, Input, Output, F, &'a (Input, Output, F, B), B, E>; +pub trait EffectiveForLt<'a, Output: 'a, E: Effect, Bound> { + type T: Effective<Output = Output, Effect = E>; } -impl<'b, T, Input: 'b, Output: 'b, ForBound, E: Effect> MutMapFnMut<'b, Input, Output, ForBound, E> - for T -where - T: FnMut(&'b mut Input) -> ObjSafe<'b, Output, E>, -{ - fn call(&mut self, input: &'b mut Input) -> ObjSafe<'b, Output, E> { - self(input) - } -} +pub trait EffectiveHrt<Output, E: Effect>: for<'a> EffectiveForLt<'a, Output, E, &'a Output> {} -pub trait MutMapFnMut<'b, FIn: 'b, FOut: 'b, ForBound, E: Effect> { - fn call(&mut self, input: &'b mut FIn) -> ObjSafe<'b, FOut, E>; -} +pub type EffectiveT<'a, V, Output, E> = <V as EffectiveForLt<'a, Output, E, &'a Output>>::T; -pub trait ForLtFnMut<'a, FIn: 'a, FOut, Output: 'a, F: 'a, ForBound, E: Effect> -where - for<'b> F: MutMapFnMut<'b, FIn, FOut, &'b (FIn, FOut), E>, -{ - type T: Adapters<'a, Effect = E, T = Output>; -} - -// pub trait ForLtFnMut<'a, Input: 'a, Output: 'a, F: 'a, B, O, E: Effect> -// where -// F: for<'b> FnMut( -// &'b mut Input, -// PhantomData<&'b O>, -// ) -> (ObjSafe<'b, Output, E>, PhantomData<&'b O>), -// { -// type T: Adapters<'a, Effect = E, T = Output>; -// } - -pub trait HktFnMut<E: Effect> { - type T<FIn, FOut, Output, F: for<'b> MutMapFnMut<'b, FIn, FOut, &'b (FIn, FOut), E>, ForBound>: for<'a> ForLtFnMut<'a, FIn, FOut, Output, F, &'a (FIn, Output, F, ForBound), E>; -} +pub trait Effective: Into<<Self::Effect as Effect>::Erased<Self::Output>> { + /// The effect the effective belongs to. + type Effect: Effect; -// pub trait HktFnMut<E: Effect> { -// type T<Input, Output, F: for<'b> FnMut(&'b mut Input, PhantomData<&'b B>) -> (ObjSafe<'b, Output, E>, PhantomData<&'b B>), B>: for<'a> ForLtFnMut<'a, Input, Output, F, &'a (Input, Output, F, B), B, E>; -// } + /// The type of the effective's output value. + type Output; -pub trait ForLtFnOwn<'a, Input: 'a, Output: 'a, F: 'a, B, O, E: Effect> -where - F: for<'b> FnOnce(Input, PhantomData<&'b O>) -> ObjSafe<'b, Output, E>, -{ - type T: Adapters<'a, Effect = E, T = Output>; -} + /// Future that resolves to the same value as the effective. + type IntoFuture: Future<Output = Self::Output>; -pub trait HktFnOwn<E: Effect> { - type T<Input, Output, F: for<'b> FnOnce(Input, PhantomData<&'b B>) -> ObjSafe<'b, Output, E>, B>: for<'a> ForLtFnOwn<'a, Input, Output, F, &'a (Input, Output, F, B),B, E>; -} + /// Convert the effective into a general future for use in async. + fn into_future(self) -> Self::IntoFuture; -// pub trait ForLtFn<'a, E: Effect> { -// type T<Input: 'a, Output: 'a, F: 'a + for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, E>>: Adapters<'a, Effect = E, T = Output>; -// } -// -// pub trait HktFn<E: Effect>: for<'a> ForLtFn<'a, E> {} - -/// Trait for effects. -pub trait Effect: Sized + Send + Sync + 'static { - type ObjSafe: Hkt<Effect = Self>; - - type Ready: Hkt<Effect = Self>; - - fn ready<'a, T: 'a>(x: T) -> <<Self::Ready as Hkt>::T<T, ()> as ForLt<'a, T, &'a (T, ())>>::T; - - type With: HktFn<Self>; - - fn with<'ctx, 'a, T: 'a, R: 'a, F: 'a>( - x: T, - f: F, - ) -> <<Self::With as HktFn<Self>>::T<T, R, F, &'ctx ()> as ForLtFn< - 'a, - T, - R, - F, - &'a (T, R, F, &'ctx ()), - &'ctx (), - Self, - >>::T + /// Effective performing a loop. + type Loop<T, V, F>: Effective<Output = (Self::Output, T), Effect = Self::Effect> where - F: for<'b> FnOnce( - &'b mut T, - PhantomData<&'b &'ctx ()>, - ) -> (ObjSafe<'b, R, Self>, PhantomData<&'b &'ctx ()>); + F: for<'a> FnMut(&'a mut Self::Output) -> EffectiveT<'a, V, ControlFlow<T>, Self::Effect>, + V: EffectiveHrt<ControlFlow<T>, Self::Effect>; - fn join<'a, T: 'a>(tuple: T) -> ObjSafe<'a, T::Output, Self> + /// 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 - T: Joinable<'a, Self>, - { - T::join(tuple) - } + F: for<'a> FnMut(&'a mut Self::Output) -> EffectiveT<'a, V, ControlFlow<T>, Self::Effect>, + V: EffectiveHrt<ControlFlow<T>, Self::Effect>; - fn try_join<'a, T: 'a>(tuple: T) -> ObjSafe<'a, Result<T::Output, T::Error>, Self> + type Map<T, F>: Effective<Output = T, Effect = Self::Effect> where - T: TryJoinable<'a, Self>, - { - T::try_join(tuple) - } -} - -pub trait Joinable<'a, E: Effect>: Sized { - type Output; - - fn join(tuple: Self) -> ObjSafe<'a, Self::Output, E>; -} - -pub struct Join<T, B>(pub T, pub Marker<B>); - -impl<'a, E: Effect, T0> Joinable<'a, E> for Join<(ObjSafe<'a, T0, E>,), (T0,)> { - fn join(Join((a,), _): Self) -> ObjSafe<'a, (T0,), E> { - a.map(|x| (x,)).into() - } + F: FnOnce(Self::Output) -> T; - type Output = (T0,); -} - -impl<'a, E: Effect, T0, T1> Joinable<'a, E> - for Join<(ObjSafe<'a, T0, E>, ObjSafe<'a, T1, E>), (T0, T1)> -{ - fn join(Join((a, b), _): Self) -> ObjSafe<'a, (T0, T1), E> { - a.then(|a, _| b.map(|b| (a, b)).into()).into() - } - - type Output = (T0, T1); -} - -pub trait TryJoinable<'a, E: Effect>: Sized { - type Output; - - type Error; - - fn try_join(tuple: Self) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E>; -} - -impl<'a, E: Effect, Err, T0, T1> TryJoinable<'a, E> - for Join< - ( - ObjSafe<'a, Result<T0, Err>, E>, - ObjSafe<'a, Result<T1, Err>, E>, - ), - (Err, T0, T1), - > -{ - fn try_join(Join((a, b), _): Self) -> ObjSafe<'a, Result<(T0, T1), Err>, E> { - a.then(|a, _| { - match a { - Ok(a) => b - .map(|b| match b { - Ok(b) => Ok((a, b)), - Err(err) => Err(err), - }) - .into(), - Err(err) => E::ready(Err(err)).into(), - } - // b.map(|b| (a, b)).into() - }) - .into() - } - - type Output = (T0, T1); - - type Error = Err; -} - -pub type ObjSafe<'a, T, E, B = ()> = - <<<E as Effect>::ObjSafe as Hkt>::T<T, B> as ForLt<'a, T, &'a (T, B)>>::T; - -pub enum Blocking {} - -pub enum ValueHkt {} - -impl Hkt for ValueHkt { - type Effect = Blocking; - - type T<Output, B> = ValueHrt<Output, B>; -} - -pub struct ValueHrt<T, B>(Marker<(T, B)>); - -impl<'a, T, B> ForLt<'a, T, &'a (T, B)> for ValueHrt<T, B> { - type Effect = Blocking; - - type T = Value<T>; -} - -pub enum WithHkt {} - -impl HktFnOwn<Blocking> for WithHkt { - type T< - Input, - Output, - F: for<'b> FnOnce(Input, PhantomData<&'b B>) -> ObjSafe<'b, Output, Blocking>, - B, - > = WithHkt; -} - -impl<'a, Input, Output, F, B> - ForLtFnOwn<'a, Input, Output, F, &'a (Input, Output, F, B), B, Blocking> for WithHkt -where - F: for<'b> FnOnce(Input, PhantomData<&'b B>) -> ObjSafe<'b, Output, Blocking>, -{ - type T = Value<Output>; -} - -impl HktFn<Blocking> for WithHkt { - type T< - Input, - Output, - F: for<'b> FnOnce( - &'b mut Input, - PhantomData<&'b B>, - ) -> (ObjSafe<'b, Output, Blocking>, PhantomData<&'b B>), - B, - > = WithHkt; -} - -impl<'a, Input, Output, F, B> ForLtFn<'a, Input, Output, F, &'a (Input, Output, F, B), B, Blocking> - for WithHkt -where - F: for<'b> FnOnce( - &'b mut Input, - PhantomData<&'b B>, - ) -> (ObjSafe<'b, Output, Blocking>, PhantomData<&'b B>), -{ - type T = Value<Output>; -} - -impl HktFnMut<Blocking> for WithHkt { - type T< - FIn, - FOut, - Output, - F: for<'b> MutMapFnMut<'b, FIn, FOut, &'b (FIn, FOut), Blocking>, - ForBound, - > = WithHkt; -} - -impl<'a, FIn, FOut, Output, F, B> - ForLtFnMut<'a, FIn, FOut, Output, F, &'a (FIn, Output, F, B), Blocking> for WithHkt -where - for<'b> F: MutMapFnMut<'b, FIn, FOut, &'b (FIn, FOut), Blocking>, -{ - type T = Value<Output>; -} - -impl Effect for Blocking { - type ObjSafe = ValueHkt; - - type Ready = ValueHkt; - - fn ready<'a, T: 'a>(x: T) -> <<Self::Ready as Hkt>::T<T, ()> as ForLt<'a, T, &'a (T, ())>>::T { - Value(x) - } - - type With = WithHkt; - - #[inline(always)] - fn with<'ctx, 'a, T: 'a, R: 'a, F: 'a>( - x: T, - f: F, - ) -> <<Self::With as HktFn<Self>>::T<T, R, F, &'ctx ()> as ForLtFn< - 'a, - T, - R, - F, - &'a (T, R, F, &'ctx ()), - &'ctx (), - Self, - >>::T + fn map<T, F>(self, cb: F) -> Self::Map<T, F> where - F: for<'b> FnOnce( - &'b mut T, - PhantomData<&'b &'ctx ()>, - ) -> (ObjSafe<'b, R, Self>, PhantomData<&'b &'ctx ()>), - { - let mut ctx = x; - f(&mut ctx, PhantomData).0 - } -} - -pub struct Value<T>(pub T); - -impl<'b, U: 'b> Adapters<'b> for Value<U> { - type Effect = Blocking; + F: FnOnce(Self::Output) -> T; - type T = U; - - type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = Value<T> where 'b: 'a; - - fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> + type Then<T, V, F>: Effective<Output = T, Effect = Self::Effect> where - F: FnOnce(Self::T) -> R, - 'b: 'a, - { - Value(f(self.0)) - } - - type AsCtxFor = WithHkt; + F: FnOnce(Self::Output) -> V, + V: Effective<Output = T, Effect = Self::Effect>; - #[inline(always)] - fn as_ctx_for<'ctx, 'a, R: 'a, F: 'a>(self, f: F) -> ObjSafe<'a, (Self::T, R), Blocking> + fn then<T, V, F>(self, cb: F) -> Self::Then<T, V, F> where - F: for<'c> FnOnce( - &'c mut Self::T, - PhantomData<&'c &'ctx ()>, - ) -> (ObjSafe<'c, R, Self::Effect>, PhantomData<&'c &'ctx ()>), - { - let mut ctx = self.0; - let value = f(&mut ctx, PhantomData).0 .0; - Value((ctx, value)) - } - - fn then<'ctx, 'a, R: 'a, F: 'a>( - self, - f: F, - ) -> <<Self::AsCtxFor as HktFnOwn<Self::Effect>>::T<Self::T, R, F, &'ctx ()> as ForLtFnOwn< - 'a, - Self::T, - R, - F, - &'a (Self::T, R, F, &'ctx ()), - &'ctx (), - Self::Effect, - >>::T - where - F: for<'c> FnOnce( - Self::T, - PhantomData<&'c &'ctx ()>, - ) -> ObjSafe<'c, R, Self::Effect>{ - f(self.0, PhantomData) - } - - #[inline(always)] - fn r#loop<'ctx, 'a, R: 'a, F: 'a>(mut self, mut f: F) -> ObjSafe<'a, R, Blocking> - where - F: for<'c> FnMut(&'c mut Self::T) -> ObjSafe<'c, ControlFlow<R>, Self::Effect>, - { - loop { - if let ControlFlow::Break(value) = f(&mut self.0).0 { - return Value(value); - } - } - } -} - -/* -pub enum Async {} - -impl Effect for Async { - type ObjSafe = BoxedFutureHkt; - - type Ready = AsyncValueHkt; - - fn ready<'a, T: 'a>(x: T) -> <<Self::Ready as Hkt>::T<T, ()> as ForLt<'a, T, &'a (T, ())>>::T { - AsyncValue(x) - } - - type With = AsyncWithHkt; + F: FnOnce(Self::Output) -> V, + V: Effective<Output = T, Effect = Self::Effect>; - fn with<'a, T: 'a, R: 'a, F: 'a>( - x: T, - f: F, - ) -> <<Self::With as HktFn<Self>>::T<T, R, F, ()> as ForLtFn< - 'a, - T, - R, - F, - &'a (T, R, F, ()), - Self, - >>::T + type AsCtx<T, V, F>: Effective<Output = (Self::Output, T), Effect = Self::Effect> where - F: FnOnce(&mut T) -> ObjSafe<'_, R, Self>, - { - BoxedFuture(Box::pin(async move { - let mut x = x; - - let fut = f(&mut x).0; - fut.await - })) - } -} - -pub enum BoxedFutureHkt {} - -impl Hkt for BoxedFutureHkt { - type Effect = Async; - - type T<Output, B> = BoxedFutureHrt<Output, B>; -} - -pub struct BoxedFutureHrt<Output, B>(Marker<(Output, B)>); - -impl<'a, Output, B> ForLt<'a, Output, &'a (Output, B)> for BoxedFutureHrt<Output, B> { - type Effect = Async; - - type T = BoxedFuture<'a, Output>; -} - -pub enum AsyncValueHkt {} - -impl Hkt for AsyncValueHkt { - type Effect = Async; + F: for<'a> FnOnce(&'a mut Self::Output) -> EffectiveT<'a, V, T, Self::Effect>, + V: EffectiveHrt<T, Self::Effect>; - type T<Output, B> = AsyncValue<Output>; -} - -pub enum AsyncWithHkt {} - -impl HktFn<Async> for AsyncWithHkt { - type T<Input, Output, F: for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, Async>, B> = - AsyncWithHkt; -} - -impl<'a, Input, Output, F, B> ForLtFn<'a, Input, Output, F, &'a (Input, Output, F, B), Async> - for AsyncWithHkt -where - F: for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, Async>, -{ - type T = BoxedFuture<'a, Output>; -} - -pub struct AsyncValue<T>(pub T); - -impl<'a, T, B> ForLt<'a, T, &'a (T, B)> for AsyncValue<T> { - type Effect = Async; - - type T = AsyncValue<T>; -} - -pub struct BoxedFuture<'a, T: 'a>(pub Pin<Box<dyn Future<Output = T> + 'a>>); - -impl<'b, U: 'b> Adapters<'b> for AsyncValue<U> { - type Effect = Async; - - type T = U; - - type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncValue<T> where 'b: 'a; - - fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> + fn as_ctx<T, V, F>(self, cb: F) -> Self::AsCtx<T, V, F> where - F: FnOnce(Self::T) -> R, - 'b: 'a, - { - AsyncValue(f(self.0)) - } + F: for<'a> FnOnce(&'a mut Self::Output) -> EffectiveT<'a, V, T, Self::Effect>, + V: EffectiveHrt<T, Self::Effect>; } -impl<'b, U: 'b> Adapters<'b> for BoxedFuture<'b, U> { - type Effect = Async; - - type T = U; - - type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncMap<Self, F> where 'b: 'a; +pub trait Join { + type Effect: Effect; - fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> + type Two<T0, T1>: Effective<Output = (T0::Output, T1::Output), Effect = Self::Effect> where - F: FnOnce(Self::T) -> R, - 'b: 'a, - { - AsyncMap { - map: futures::FutureExt::map(self, f), - } - } -} - -#[pin_project] -pub struct AsyncMap<Fut, F> { - #[pin] - map: futures::future::Map<Fut, F>, -} + T0: Effective<Effect = Self::Effect>, + T1: Effective<Effect = Self::Effect>; -impl<'b, U: 'b, Fut0: 'b, F0: 'b> Adapters<'b> for AsyncMap<Fut0, F0> -where - Fut0: Future, - F0: FnOnce(Fut0::Output) -> U, -{ - type Effect = Async; - - type T = U; - - type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncMap<Self, F> where 'b: 'a; - - fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> + type Three<T0, T1, T2>: Effective< + Output = (T0::Output, T1::Output, T2::Output), + Effect = Self::Effect, + > where - F: FnOnce(Self::T) -> R, - 'b: 'a, - { - AsyncMap { - map: futures::FutureExt::map(self, f), - } - } -} - -impl<T, Fut, F> Future for AsyncMap<Fut, F> -where - Fut: Future, - F: FnOnce(Fut::Output) -> T, -{ - type Output = T; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - let this = self.project(); - this.map.poll(cx) - } -} - -impl<'a, T> Future for BoxedFuture<'a, T> { - type Output = T; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { - self.0.poll_unpin(cx) - } -} - -impl<'a, T, Fut: 'a, F: 'a> From<AsyncMap<Fut, F>> for BoxedFuture<'a, T> -where - Fut: Future, - F: FnOnce(Fut::Output) -> T, -{ - fn from(value: AsyncMap<Fut, F>) -> Self { - BoxedFuture(Box::pin(value.map)) - } -} - -impl<'a, T: 'a> From<AsyncValue<T>> for BoxedFuture<'a, T> { - fn from(value: AsyncValue<T>) -> Self { - BoxedFuture(Box::pin(futures::future::ready(value.0))) - } -} -*/ - -/* -pub trait ReadyValue: core::future::Future { - fn value(self) -> Self::Output; -} - -impl<T: Send> ReadyValue for core::future::Ready<T> { - fn value(self) -> Self::Output { - Spin::block_on(self) - } -} + T0: Effective<Effect = Self::Effect>, + T1: Effective<Effect = Self::Effect>, + T2: Effective<Effect = Self::Effect>; -pub trait BlockOn: 'static { - fn block_on<F>(future: F) -> F::Output + fn two<T0, T1, F0, F1>(cb: (F0, F1)) -> Self::Two<T0, T1> where - F: core::future::Future + Send, - <F as core::future::Future>::Output: Send; -} - -/// [`BlockOn`] implementer that just spins on the future. -/// -/// This is useful for futures that are alwayd ready. -pub enum Spin {} + T0: Effective<Effect = Self::Effect>, + T1: Effective<Effect = Self::Effect>, + F0: FnOnce() -> T0, + F1: FnOnce() -> T1; -impl BlockOn for Spin { - #[inline(always)] - fn block_on<F>(future: F) -> F::Output + fn three<T0, T1, T2, F0, F1, F2>(effectives: (F0, F1, F2)) -> Self::Three<T0, T1, T2> where - F: core::future::Future + Send, - { - let waker = noop(); - let mut context = Context::from_waker(&waker); - - let mut future = pin!(future); - loop { - if let Poll::Ready(value) = future.as_mut().poll(&mut context) { - return value; - } - } - } -} - -#[inline] -pub fn noop() -> Waker { - const VTABLE: &RawWakerVTable = &RawWakerVTable::new( - // Cloning just returns a new no-op raw waker - |_| RAW, - // `wake` does nothing - |_| {}, - // `wake_by_ref` does nothing - |_| {}, - // Dropping does nothing as we don't allocate anything - |_| {}, - ); - const RAW: RawWaker = RawWaker::new(ptr::null(), VTABLE); - unsafe { Waker::from_raw(RAW) } + T0: Effective<Effect = Self::Effect>, + T1: Effective<Effect = Self::Effect>, + T2: Effective<Effect = Self::Effect>, + F0: FnOnce() -> T0, + F1: FnOnce() -> T1, + F2: FnOnce() -> T2; } -// pub struct Ready<Output> { -// pub value: Option<Output>, -// } -// -// impl<Output> Ready<Output> { -// pub fn into_inner(self) -> Output { -// self.value.expect("`into_inner` called after completion") -// } -// } -// -// impl<Output> Unpin for Ready<Output> {} -// -// impl<Output> core::future::Future for Ready<Output> { -// type Output = Output; -// -// fn poll(mut self: core::pin::Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { -// Poll::Ready(self.value.take().expect("`Ready` polled after completion")) -// } -// } - -higher_ranked_type! { - impl SendFuture { - impl['a, Output] type T['a, Output] for core::future::Ready<Output> = - core::future::Ready<Output> - where { - Output: Send - }; - - impl['a, Output] type HigherRanked['a, Output] for core::future::Ready<Output> = - core::future::Ready<Output> - where { - Output: Send - }; - } -} - -impl<B: BlockOn> Effect for Blocking<B> { - type Future<T: Send> = core::future::Ready<T>; +pub trait TryJoin { + type Effect: Effect; - #[inline(always)] - fn wrap<'a, F>(future: F) -> SendFuture::T<'a, F::Output, Self::Future<F::Output>> + type Two<Err, V0, V1, T0, T1>: Effective<Output = Result<(T0, T1), Err>, Effect = Self::Effect> where - F: core::future::Future + Send + 'a, - <F as core::future::Future>::Output: Send, - { - core::future::ready(B::block_on(future)) - } - - #[inline(always)] - fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, T, Self::Future<T>> { - core::future::ready(value) - } - - #[inline(always)] - fn map<'a, T, U, F>( - future: SendFuture::T<'a, T, Self::Future<T>>, - func: F, - ) -> SendFuture::T<'a, U, Self::Future<U>> - where - T: Send, - U: Send, - F: FnOnce(T) -> U + Send + 'a, - { - let value = B::block_on(future); - core::future::ready(func(value)) - } -} - -mod sealed { - pub enum BoxedFuture<'lt, Output> { - Box(core::pin::Pin<Box<dyn core::future::Future<Output = Output> + Send + 'lt>>), - Ready(core::future::Ready<Output>), - } - - impl<'lt, Output> core::future::Future for BoxedFuture<'lt, Output> { - type Output = Output; - - fn poll( - mut self: core::pin::Pin<&mut Self>, - cx: &mut core::task::Context<'_>, - ) -> core::task::Poll<Self::Output> { - match &mut *self { - BoxedFuture::Box(future) => future.as_mut().poll(cx), - BoxedFuture::Ready(future) => core::pin::Pin::new(future).poll(cx), - } - } - } -} - -#[cfg(feature = "alloc")] -pub struct BoxedFutureHrt<Output>(Marker<Output>); - -#[cfg(feature = "alloc")] -higher_ranked_type! { - impl SendFuture { - impl['a, Output] type T['a, Output] for BoxedFutureHrt<Output> = - sealed::BoxedFuture<'a, Output> - where { - Output: Send - }; - - impl['a, Output] type HigherRanked['a, Output] for sealed::BoxedFuture<'a, Output> = - BoxedFutureHrt<Output> - where { - Output: Send - }; - } -} + V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>, + V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>; -#[cfg(feature = "alloc")] -pub enum Async {} - -#[cfg(feature = "alloc")] -impl Effect for Async { - type Future<T: Send> = BoxedFutureHrt<T>; - - fn wrap<'a, F>(future: F) -> SendFuture::T<'a, F::Output, Self::Future<F::Output>> + type Three<Err, V0, V1, V2, T0, T1, T2>: Effective< + Output = Result<(T0, T1, T2), Err>, + Effect = Self::Effect, + > where - F: core::future::Future + Send + 'a, - <F as core::future::Future>::Output: Send, - { - sealed::BoxedFuture::Box(Box::pin(future)) - } - - fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, T, Self::Future<T>> { - sealed::BoxedFuture::Ready(core::future::ready(value)) - } - - fn map<'a, T, U, F>( - future: SendFuture::T<'a, T, Self::Future<T>>, - func: F, - ) -> SendFuture::T<'a, U, Self::Future<U>> + V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>, + V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>, + V2: Effective<Output = Result<T2, Err>, Effect = Self::Effect>; + + fn two<Err, T0, T1, V0, V1, F0, F1>(cb: (F0, F1)) -> Self::Two<Err, V0, V1, T0, T1> where - T: Send, - U: Send, - F: FnOnce(T) -> U + Send + 'a, - { - match future { - sealed::BoxedFuture::Box(future) => Self::wrap(async { func(future.await) }), - sealed::BoxedFuture::Ready(future) => { - let value = Spin::block_on(future); - Self::ready(func(value)) - } - } - } - - fn wrap_boxed<'a, F>( - future: core::pin::Pin<Box<F>>, - ) -> SendFuture::T<'a, F::Output, Self::Future<F::Output>> + V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>, + V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>, + F0: FnOnce() -> T0, + F1: FnOnce() -> T1; + + fn three<Err, T0, T1, T2, V0, V1, V2, F0, F1, F2>( + cb: (F0, F1, F2), + ) -> Self::Three<Err, V0, V1, V2, T0, T1, T2> where - F: core::future::Future + Send + 'a, - <F as core::future::Future>::Output: Send, - { - sealed::BoxedFuture::Box(future) - } + V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>, + V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>, + V2: Effective<Output = Result<T2, Err>, Effect = Self::Effect>, + F0: FnOnce() -> T0, + F1: FnOnce() -> T1, + F2: FnOnce() -> T2; } -*/ diff --git a/src/effect/blocking.rs b/src/effect/blocking.rs new file mode 100644 index 0000000..ea97477 --- /dev/null +++ b/src/effect/blocking.rs @@ -0,0 +1,164 @@ +use super::*; + +pub enum Blocking {} + +pub struct Value<T>(pub T); + +impl Effect for Blocking { + type Erased<T> = Value<T>; + + type Ready<T> = Value<T>; + + fn ready<T>(value: T) -> Self::Ready<T> { + todo!() + } + + type FromFuture<F> = Value<F::Output> + where + F: Future; + + fn from_future<F>() -> Self::FromFuture<F> + where + F: Future, + { + todo!() + } +} + +impl<U> Effective for Value<U> { + type Effect = Blocking; + + type Output = U; + + type IntoFuture = core::future::Ready<U>; + + fn into_future(self) -> Self::IntoFuture { + todo!() + } + + type Loop<T, V, F> = Value<T> + where + F: for<'a> FnMut(&'a mut Self::Output) -> EffectiveT<'a, V, ControlFlow<T>, Self::Effect>, + V: EffectiveHrt<ControlFlow<T>, Self::Effect>; + + fn r#loop<T, V, F>(self, cb: F) -> Self::Loop<T, V, F> + where + F: for<'a> FnMut(&'a mut Self::Output) -> EffectiveT<'a, V, ControlFlow<T>, Self::Effect>, + V: EffectiveHrt<ControlFlow<T>, Self::Effect>, + { + todo!() + } + + type Map<T, F> = Value<T> + where + F: FnOnce(Self::Output) -> T; + + fn map<T, F>(self, cb: F) -> Self::Map<T, F> + where + F: FnOnce(Self::Output) -> T, + { + todo!() + } + + type Then<T, V, F> = Value<T> + where + F: FnOnce(Self::Output) -> V, + V: Effective<Output = T, Effect = Self::Effect>; + + fn then<T, V, F>(self, cb: F) -> Self::Then<T, V, F> + where + F: FnOnce(Self::Output) -> V, + V: Effective<Output = T, Effect = Self::Effect>, + { + todo!() + } + + type AsCtx<T, V, F> = Value<T> + where + F: for<'a> FnOnce(&'a mut Self::Output) -> EffectiveT<'a, V, T, Self::Effect>, + V: EffectiveHrt<T, Self::Effect>; + + fn as_ctx<T, V, F>(self, cb: F) -> Self::AsCtx<T, V, F> + where + F: for<'a> FnOnce(&'a mut Self::Output) -> EffectiveT<'a, V, T, Self::Effect>, + V: EffectiveHrt<T, Self::Effect>, + { + todo!() + } +} + +impl Join for Blocking { + type Effect = Self; + + type Two<T0, T1> = Value<(T0::Output, T1::Output)> + where + T0: Effective<Effect = Self::Effect>, + T1: Effective<Effect = Self::Effect>; + + type Three<T0, T1, T2> = Value<(T0::Output, T1::Output, T2::Output)> + where + T0: Effective<Effect = Self::Effect>, + T1: Effective<Effect = Self::Effect>, + T2: Effective<Effect = Self::Effect>; + + fn two<T0, T1, F0, F1>(cb: (F0, F1)) -> Self::Two<T0, T1> + where + T0: Effective<Effect = Self::Effect>, + T1: Effective<Effect = Self::Effect>, + F0: FnOnce() -> T0, + F1: FnOnce() -> T1, + { + todo!() + } + + fn three<T0, T1, T2, F0, F1, F2>(effectives: (F0, F1, F2)) -> Self::Three<T0, T1, T2> + where + T0: Effective<Effect = Self::Effect>, + T1: Effective<Effect = Self::Effect>, + T2: Effective<Effect = Self::Effect>, + F0: FnOnce() -> T0, + F1: FnOnce() -> T1, + F2: FnOnce() -> T2, + { + todo!() + } +} + +impl TryJoin for Blocking { + type Effect = Self; + + type Two<Err, V0, V1, T0, T1> = Value<Result<(T0, T1), Err>> + where + V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>, + V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>; + + type Three<Err, V0, V1, V2, T0, T1, T2> = Value<Result<(T0, T1, T2), Err>> + where + V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>, + V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>, + V2: Effective<Output = Result<T2, Err>, Effect = Self::Effect>; + + fn two<Err, T0, T1, V0, V1, F0, F1>(cb: (F0, F1)) -> Self::Two<Err, V0, V1, T0, T1> + where + V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>, + V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>, + F0: FnOnce() -> T0, + F1: FnOnce() -> T1, + { + todo!() + } + + fn three<Err, T0, T1, T2, V0, V1, V2, F0, F1, F2>( + cb: (F0, F1, F2), + ) -> Self::Three<Err, V0, V1, V2, T0, T1, T2> + where + V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>, + V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>, + V2: Effective<Output = Result<T2, Err>, Effect = Self::Effect>, + F0: FnOnce() -> T0, + F1: FnOnce() -> T1, + F2: FnOnce() -> T2, + { + todo!() + } +} @@ -8,18 +8,18 @@ extern crate alloc; pub mod any; -mod build; +// mod build; pub mod effect; pub mod hkt; -pub mod macros; -pub mod protocol; +// pub mod macros; +// pub mod protocol; pub mod symbol; -mod transform; -mod walk; +// mod transform; +// mod walk; -pub use build::*; -pub use transform::*; -pub use walk::*; +// pub use build::*; +// pub use transform::*; +// pub use walk::*; use symbol::Symbol; |