This commit is contained in:
AF 2024-05-13 22:38:27 +03:00
parent 887807c740
commit 509241a682
Signed by: alisa
SSH Key Fingerprint: SHA256:vNY4pdIZvO1FYJKHROkdHLtvyopizvZVAEwg9AF6h04

View File

@ -10,12 +10,12 @@ use pin_project::pin_project;
pub trait Trait {
type Associated: ?Sized + Trait;
type In<'out: 'tmp, 'tmp, I: 'tmp>;
type Out<'out, A>;
type Out<'out, I: Impl<Self>>;
}
pub trait Impl<T: ?Sized + Trait>: Sized {
type Associated: Impl<T::Associated>;
fn method<'out: 'tmp, 'tmp>(_: T::In<'out, 'tmp, Self>) -> T::Out<'out, Self::Associated>
fn method<'out: 'tmp, 'tmp>(_: T::In<'out, 'tmp, Self>) -> T::Out<'out, Self>
where
Self: 'tmp;
}
@ -45,7 +45,7 @@ pub struct Is<That, T: ?Sized>(That, T);
impl<That, T: ?Sized + Trait> Trait for Is<That, T> {
type Associated = T;
type In<'out: 'tmp, 'tmp, I: 'tmp> = I;
type Out<'out, A> = That;
type Out<'out, I: Impl<Self>> = That;
}
impl<That: Impl<T>, T: ?Sized + Trait> Impl<Is<Self, T>> for That {
@ -66,7 +66,7 @@ pub struct To<T: ?Sized>(T);
impl<T: ?Sized + Trait> Trait for To<T> {
type Associated = T;
type In<'out: 'tmp, 'tmp, I: 'tmp> = I;
type Out<'out, A> = A;
type Out<'out, I: Impl<Self>> = I::Associated;
}
impl<I: FnOnce() -> Output, Output: Impl<T>, T: ?Sized + Trait> Impl<To<T>> for I {
@ -74,7 +74,7 @@ impl<I: FnOnce() -> Output, Output: Impl<T>, T: ?Sized + Trait> Impl<To<T>> for
fn method<'out: 'tmp, 'tmp>(
this: <To<T> as Trait>::In<'out, 'tmp, Self>,
) -> <To<T> as Trait>::Out<'out, Self::Associated>
) -> <To<T> as Trait>::Out<'out, Self>
where
Self: 'tmp,
{
@ -282,7 +282,7 @@ pub struct FutureTo<T: ?Sized>(T);
impl<T: ?Sized + Trait> Trait for FutureTo<T> {
type Associated = T;
type In<'out: 'tmp, 'tmp, I: 'tmp> = (Pin<&'tmp mut I>, &'tmp mut Context<'out>);
type Out<'out, A> = Poll<A>;
type Out<'out, I: Impl<Self>> = Poll<I::Associated>;
}
impl<T: ?Sized + Trait, Output: Impl<T>, F: Future<Output = Output>> Impl<FutureTo<T>> for F {
@ -290,7 +290,7 @@ impl<T: ?Sized + Trait, Output: Impl<T>, F: Future<Output = Output>> Impl<Future
fn method<'out: 'tmp, 'tmp>(
(this, cx): <FutureTo<T> as Trait>::In<'out, 'tmp, Self>,
) -> <FutureTo<T> as Trait>::Out<'out, Self::Associated>
) -> <FutureTo<T> as Trait>::Out<'out, Self>
where
Self: 'tmp,
{
@ -368,3 +368,151 @@ fn doubly_futures() {
let x = futures::executor::block_on(Futures::flatten(x).into_future_()).into_::<i32>();
assert_eq!(x, 10);
}
struct TracePure;
struct TraceMap<T>(T);
struct TraceJoin<T0, T1>(T0, T1);
struct TraceFlatten<T0, T1>(T0, T1);
pub trait AsTrace {
fn as_trace(&self) -> Trace;
}
pub enum Trace<'trace> {
Pure,
Flatten(&'trace dyn AsTrace, &'trace dyn AsTrace),
Map(&'trace dyn AsTrace),
Join(&'trace dyn AsTrace, &'trace dyn AsTrace),
}
impl AsTrace for TracePure {
fn as_trace(&self) -> Trace {
Trace::Pure
}
}
impl<T: AsTrace> AsTrace for TraceMap<T> {
fn as_trace(&self) -> Trace {
Trace::Map(&self.0)
}
}
impl<T0: AsTrace, T1: AsTrace> AsTrace for TraceJoin<T0, T1> {
fn as_trace(&self) -> Trace {
Trace::Join(&self.0, &self.1)
}
}
impl<T0: AsTrace, T1: AsTrace> AsTrace for TraceFlatten<T0, T1> {
fn as_trace(&self) -> Trace {
Trace::Flatten(&self.0, &self.1)
}
}
struct DynTrace<I>(I, fn(&I) -> Trace);
impl<I> AsTrace for DynTrace<I> {
fn as_trace(&self) -> Trace {
self.1(&self.0)
}
}
struct WithTrace<A, T> {
value: Option<A>,
trace: T,
}
impl<A, T: AsTrace> AsTrace for WithTrace<A, T> {
fn as_trace(&self) -> Trace {
self.trace.as_trace()
}
}
pub struct Traced<Etc: ?Sized>(Etc);
impl<Etc: ?Sized + Trait> Trait for Traced<Etc> {
type Associated = Etc;
type In<'out: 'tmp, 'tmp, I: 'tmp> = I;
type Out<'out, I: Impl<Self>> = (I::Associated, I, fn(&I) -> Trace);
}
impl<Etc: ?Sized + Trait, T: AsTrace, A: Impl<Etc>> Impl<Traced<Etc>> for WithTrace<A, T> {
type Associated = A;
fn method<'out: 'tmp, 'tmp>(
mut this: <Traced<Etc> as Trait>::In<'out, 'tmp, Self>,
) -> <Traced<Etc> as Trait>::Out<'out, Self>
where
Self: 'tmp,
{
let value = this.value.take().expect("duplicate tracing extraction");
(value, this, Self::as_trace)
}
}
trait SplitTrace<T: ?Sized> {
type Value;
fn split_trace(self) -> (Self::Value, impl AsTrace);
}
impl<T: ?Sized + Trait, I: Impl<Traced<T>>> SplitTrace<T> for I {
type Value = I::Associated;
fn split_trace(self) -> (Self::Value, impl AsTrace) {
let (value, this, method) = I::method(self);
(value, DynTrace(this, method))
}
}
pub struct Traces;
impl Functor for Traces {
type W<T: ?Sized + Trait> = Traced<T>;
fn pure<A: ?Sized + Trait>(a: impl Impl<A>) -> impl Impl<Self::W<A>> {
WithTrace {
value: Some(a),
trace: TracePure,
}
}
fn map<A: ?Sized + Trait, F: TraitFn<A>>(
a: impl Impl<Self::W<A>>,
f: F,
) -> impl Impl<Self::W<F::Out>> {
let (a, ta) = a.split_trace();
WithTrace {
value: Some(f.run(a)),
trace: TraceMap(ta),
}
}
}
impl Applicative for Traces {
fn map2<A: ?Sized + Trait, B: ?Sized + Trait, F: TraitFn2<A, B>>(
a: impl Impl<Self::W<A>>,
b: impl Impl<Self::W<B>>,
f: F,
) -> impl Impl<Self::W<F::Out>> {
let (a, ta) = a.split_trace();
let (b, tb) = b.split_trace();
WithTrace {
value: Some(f.run(a, b)),
trace: TraceJoin(ta, tb),
}
}
}
impl Monad for Traces {
fn flatten<A: ?Sized + Trait>(a: impl Impl<Self::W<Self::W<A>>>) -> impl Impl<Self::W<A>> {
let (a, to) = a.split_trace();
let (a, ti) = a.split_trace();
WithTrace {
value: Some(a),
trace: TraceFlatten(to, ti),
}
}
}