refactored effects
Konnor Andrews 2024-05-19
parent 9434269 · commit 8382bca
-rw-r--r--src/effect.rs937
-rw-r--r--src/effect/blocking.rs164
-rw-r--r--src/lib.rs16
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!()
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 6fd3a2a..c103de6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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;