Compare commits
No commits in common. "509241a68242f405c8cbd11983830ef272c8949c" and "b28faf500ae8900df39f4a23fb02b940ff793ab5" have entirely different histories.
509241a682
...
b28faf500a
273
src/model_03.rs
273
src/model_03.rs
@ -4,18 +4,18 @@ use std::{
|
|||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
use futures::{join, Future};
|
use futures::Future;
|
||||||
use pin_project::pin_project;
|
use pin_project::pin_project;
|
||||||
|
|
||||||
pub trait Trait {
|
pub trait Trait {
|
||||||
type Associated: ?Sized + Trait;
|
type Associated: ?Sized + Trait;
|
||||||
type In<'out: 'tmp, 'tmp, I: 'tmp>;
|
type In<'out: 'tmp, 'tmp, I: 'tmp>;
|
||||||
type Out<'out, I: Impl<Self>>;
|
type Out<'out, A>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Impl<T: ?Sized + Trait>: Sized {
|
pub trait Impl<T: ?Sized + Trait>: Sized {
|
||||||
type Associated: Impl<T::Associated>;
|
type Associated: Impl<T::Associated>;
|
||||||
fn method<'out: 'tmp, 'tmp>(_: T::In<'out, 'tmp, Self>) -> T::Out<'out, Self>
|
fn method<'out: 'tmp, 'tmp>(_: T::In<'out, 'tmp, Self>) -> T::Out<'out, Self::Associated>
|
||||||
where
|
where
|
||||||
Self: 'tmp;
|
Self: 'tmp;
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ pub struct Is<That, T: ?Sized>(That, T);
|
|||||||
impl<That, T: ?Sized + Trait> Trait for Is<That, T> {
|
impl<That, T: ?Sized + Trait> Trait for Is<That, T> {
|
||||||
type Associated = T;
|
type Associated = T;
|
||||||
type In<'out: 'tmp, 'tmp, I: 'tmp> = I;
|
type In<'out: 'tmp, 'tmp, I: 'tmp> = I;
|
||||||
type Out<'out, I: Impl<Self>> = That;
|
type Out<'out, A> = That;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<That: Impl<T>, T: ?Sized + Trait> Impl<Is<Self, T>> for 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> {
|
impl<T: ?Sized + Trait> Trait for To<T> {
|
||||||
type Associated = T;
|
type Associated = T;
|
||||||
type In<'out: 'tmp, 'tmp, I: 'tmp> = I;
|
type In<'out: 'tmp, 'tmp, I: 'tmp> = I;
|
||||||
type Out<'out, I: Impl<Self>> = I::Associated;
|
type Out<'out, A> = A;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: FnOnce() -> Output, Output: Impl<T>, T: ?Sized + Trait> Impl<To<T>> for I {
|
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>(
|
fn method<'out: 'tmp, 'tmp>(
|
||||||
this: <To<T> as Trait>::In<'out, 'tmp, Self>,
|
this: <To<T> as Trait>::In<'out, 'tmp, Self>,
|
||||||
) -> <To<T> as Trait>::Out<'out, Self>
|
) -> <To<T> as Trait>::Out<'out, Self::Associated>
|
||||||
where
|
where
|
||||||
Self: 'tmp,
|
Self: 'tmp,
|
||||||
{
|
{
|
||||||
@ -87,11 +87,6 @@ pub trait TraitFn<In: ?Sized + Trait> {
|
|||||||
fn run(self, _: impl Impl<In>) -> impl Impl<Self::Out>;
|
fn run(self, _: impl Impl<In>) -> impl Impl<Self::Out>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TraitFn2<In0: ?Sized + Trait, In1: ?Sized + Trait> {
|
|
||||||
type Out: ?Sized + Trait;
|
|
||||||
fn run(self, _: impl Impl<In0>, _: impl Impl<In1>) -> impl Impl<Self::Out>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Functor {
|
pub trait Functor {
|
||||||
type W<T: ?Sized + Trait>: ?Sized + Trait;
|
type W<T: ?Sized + Trait>: ?Sized + Trait;
|
||||||
fn pure<A: ?Sized + Trait>(_: impl Impl<A>) -> impl Impl<Self::W<A>>;
|
fn pure<A: ?Sized + Trait>(_: impl Impl<A>) -> impl Impl<Self::W<A>>;
|
||||||
@ -101,18 +96,6 @@ pub trait Functor {
|
|||||||
) -> impl Impl<Self::W<F::Out>>;
|
) -> impl Impl<Self::W<F::Out>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Applicative: Functor {
|
|
||||||
fn map2<A: ?Sized + Trait, B: ?Sized + Trait, F: TraitFn2<A, B>>(
|
|
||||||
_: impl Impl<Self::W<A>>,
|
|
||||||
_: impl Impl<Self::W<B>>,
|
|
||||||
_: F,
|
|
||||||
) -> impl Impl<Self::W<F::Out>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Monad: Functor {
|
|
||||||
fn flatten<A: ?Sized + Trait>(_: impl Impl<Self::W<Self::W<A>>>) -> impl Impl<Self::W<A>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Verbatim;
|
pub struct Verbatim;
|
||||||
|
|
||||||
impl Functor for Verbatim {
|
impl Functor for Verbatim {
|
||||||
@ -130,22 +113,6 @@ impl Functor for Verbatim {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Applicative for Verbatim {
|
|
||||||
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>> {
|
|
||||||
f.run(a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Monad for Verbatim {
|
|
||||||
fn flatten<A: ?Sized + Trait>(a: impl Impl<Self::W<Self::W<A>>>) -> impl Impl<Self::W<A>> {
|
|
||||||
a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Call<T: ?Sized + Trait> {
|
pub trait Call<T: ?Sized + Trait> {
|
||||||
type Output: Impl<T>;
|
type Output: Impl<T>;
|
||||||
fn call(self) -> Self::Output;
|
fn call(self) -> Self::Output;
|
||||||
@ -176,25 +143,9 @@ impl Functor for Lazy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Applicative for Lazy {
|
|
||||||
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>> {
|
|
||||||
|| f.run(a.call(), b.call())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Monad for Lazy {
|
|
||||||
fn flatten<A: ?Sized + Trait>(a: impl Impl<Self::W<Self::W<A>>>) -> impl Impl<Self::W<A>> {
|
|
||||||
|| a.call().call()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Composition<Uo, Ui>(Uo, Ui);
|
pub struct Composition<Uo, Ui>(Uo, Ui);
|
||||||
|
|
||||||
impl<Uo: Functor, Ui: Functor> Functor for Composition<Uo, Ui> {
|
impl<Uo: Functor, Ui: Functor> Functor for Composition<Ui, Uo> {
|
||||||
type W<T: ?Sized + Trait> = Uo::W<Ui::W<T>>;
|
type W<T: ?Sized + Trait> = Uo::W<Ui::W<T>>;
|
||||||
|
|
||||||
fn pure<A: ?Sized + Trait>(a: impl Impl<A>) -> impl Impl<Self::W<A>> {
|
fn pure<A: ?Sized + Trait>(a: impl Impl<A>) -> impl Impl<Self::W<A>> {
|
||||||
@ -205,38 +156,17 @@ impl<Uo: Functor, Ui: Functor> Functor for Composition<Uo, Ui> {
|
|||||||
a: impl Impl<Self::W<A>>,
|
a: impl Impl<Self::W<A>>,
|
||||||
f: F,
|
f: F,
|
||||||
) -> impl Impl<Self::W<F::Out>> {
|
) -> impl Impl<Self::W<F::Out>> {
|
||||||
struct Tmp<A: ?Sized, F, Ui>(F, PhantomData<(Ui, A)>);
|
struct Tmp<A: ?Sized, F, Uo, Ui>(F, PhantomData<(Uo, Ui, A)>);
|
||||||
impl<A: ?Sized + Trait, F: TraitFn<A>, Ui: Functor> TraitFn<Ui::W<A>> for Tmp<A, F, Ui> {
|
impl<A: ?Sized + Trait, F: TraitFn<A>, Uo: Functor, Ui: Functor> TraitFn<Ui::W<A>>
|
||||||
|
for Tmp<A, F, Uo, Ui>
|
||||||
|
{
|
||||||
type Out = Ui::W<F::Out>;
|
type Out = Ui::W<F::Out>;
|
||||||
|
|
||||||
fn run(self, a: impl Impl<Ui::W<A>>) -> impl Impl<Self::Out> {
|
fn run(self, a: impl Impl<Ui::W<A>>) -> impl Impl<Self::Out> {
|
||||||
Ui::map(a, self.0)
|
Ui::map(a, self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Uo::map(a, Tmp::<A, F, Ui>(f, PhantomData))
|
Uo::map(a, Tmp::<A, F, Uo, Ui>(f, PhantomData))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Uo: Applicative, Ui: Applicative> Applicative for Composition<Uo, Ui> {
|
|
||||||
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>> {
|
|
||||||
struct Tmp<A: ?Sized, B: ?Sized, F, Ui>(
|
|
||||||
F,
|
|
||||||
PhantomData<(Ui, PhantomData<A>, PhantomData<B>)>,
|
|
||||||
);
|
|
||||||
impl<A: ?Sized + Trait, B: ?Sized + Trait, F: TraitFn2<A, B>, Ui: Applicative>
|
|
||||||
TraitFn2<Ui::W<A>, Ui::W<B>> for Tmp<A, B, F, Ui>
|
|
||||||
{
|
|
||||||
type Out = Ui::W<F::Out>;
|
|
||||||
|
|
||||||
fn run(self, a: impl Impl<Ui::W<A>>, b: impl Impl<Ui::W<B>>) -> impl Impl<Self::Out> {
|
|
||||||
Ui::map2(a, b, self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Uo::map2(a, b, Tmp::<A, B, F, Ui>(f, PhantomData))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +212,7 @@ pub struct FutureTo<T: ?Sized>(T);
|
|||||||
impl<T: ?Sized + Trait> Trait for FutureTo<T> {
|
impl<T: ?Sized + Trait> Trait for FutureTo<T> {
|
||||||
type Associated = T;
|
type Associated = T;
|
||||||
type In<'out: 'tmp, 'tmp, I: 'tmp> = (Pin<&'tmp mut I>, &'tmp mut Context<'out>);
|
type In<'out: 'tmp, 'tmp, I: 'tmp> = (Pin<&'tmp mut I>, &'tmp mut Context<'out>);
|
||||||
type Out<'out, I: Impl<Self>> = Poll<I::Associated>;
|
type Out<'out, A> = Poll<A>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Trait, Output: Impl<T>, F: Future<Output = Output>> Impl<FutureTo<T>> for F {
|
impl<T: ?Sized + Trait, Output: Impl<T>, F: Future<Output = Output>> Impl<FutureTo<T>> for F {
|
||||||
@ -290,7 +220,7 @@ impl<T: ?Sized + Trait, Output: Impl<T>, F: Future<Output = Output>> Impl<Future
|
|||||||
|
|
||||||
fn method<'out: 'tmp, 'tmp>(
|
fn method<'out: 'tmp, 'tmp>(
|
||||||
(this, cx): <FutureTo<T> as Trait>::In<'out, 'tmp, Self>,
|
(this, cx): <FutureTo<T> as Trait>::In<'out, 'tmp, Self>,
|
||||||
) -> <FutureTo<T> as Trait>::Out<'out, Self>
|
) -> <FutureTo<T> as Trait>::Out<'out, Self::Associated>
|
||||||
where
|
where
|
||||||
Self: 'tmp,
|
Self: 'tmp,
|
||||||
{
|
{
|
||||||
@ -334,25 +264,6 @@ impl Functor for Futures {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Applicative for Futures {
|
|
||||||
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>> {
|
|
||||||
async {
|
|
||||||
let (a, b) = join!(a.into_future_(), b.into_future_());
|
|
||||||
f.run(a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Monad for Futures {
|
|
||||||
fn flatten<A: ?Sized + Trait>(a: impl Impl<Self::W<Self::W<A>>>) -> impl Impl<Self::W<A>> {
|
|
||||||
async { a.into_future_().await.into_future_().await }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn with_futures() {
|
fn with_futures() {
|
||||||
type U = Futures;
|
type U = Futures;
|
||||||
@ -360,159 +271,3 @@ fn with_futures() {
|
|||||||
let x = futures::executor::block_on(x.into_future_()).into_::<i32>();
|
let x = futures::executor::block_on(x.into_future_()).into_::<i32>();
|
||||||
assert_eq!(x, 10);
|
assert_eq!(x, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn doubly_futures() {
|
|
||||||
type U = Composition<Futures, Futures>;
|
|
||||||
let x = generic_test::<U>();
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user