I've ran out of cat sounds to put in commit messages
This commit is contained in:
AF 2024-05-13 20:54:29 +03:00
parent deb96a3692
commit b28faf500a
Signed by: alisa
SSH Key Fingerprint: SHA256:vNY4pdIZvO1FYJKHROkdHLtvyopizvZVAEwg9AF6h04
2 changed files with 274 additions and 0 deletions

View File

@ -2,3 +2,4 @@ pub mod model_00;
pub mod model_01; pub mod model_01;
#[cfg(any())] #[cfg(any())]
pub mod model_02; // ICE pub mod model_02; // ICE
pub mod model_03;

273
src/model_03.rs Normal file
View File

@ -0,0 +1,273 @@
use std::{
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use futures::Future;
use pin_project::pin_project;
pub trait Trait {
type Associated: ?Sized + Trait;
type In<'out: 'tmp, 'tmp, I: 'tmp>;
type Out<'out, A>;
}
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>
where
Self: 'tmp;
}
pub enum Empty {}
impl Trait for Empty {
type Associated = Self;
type In<'out: 'tmp, 'tmp, I: 'tmp> = Self;
type Out<'out, A> = Self;
}
impl<I> Impl<Empty> for I {
type Associated = I;
fn method<'out: 'tmp, 'tmp>(
empty: <Empty as Trait>::In<'out, 'tmp, Self>,
) -> <Empty as Trait>::Out<'out, Self::Associated>
where
Self: 'tmp,
{
empty
}
}
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;
}
impl<That: Impl<T>, T: ?Sized + Trait> Impl<Is<Self, T>> for That {
type Associated = Self;
fn method<'out: 'tmp, 'tmp>(
this: <Is<That, T> as Trait>::In<'out, 'tmp, Self>,
) -> <Is<That, T> as Trait>::Out<'out, Self::Associated>
where
Self: 'tmp,
{
this
}
}
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;
}
impl<I: FnOnce() -> Output, Output: Impl<T>, T: ?Sized + Trait> Impl<To<T>> for I {
type Associated = Output;
fn method<'out: 'tmp, 'tmp>(
this: <To<T> as Trait>::In<'out, 'tmp, Self>,
) -> <To<T> as Trait>::Out<'out, Self::Associated>
where
Self: 'tmp,
{
this()
}
}
pub trait TraitFn<In: ?Sized + Trait> {
type Out: ?Sized + Trait;
fn run(self, _: impl Impl<In>) -> impl Impl<Self::Out>;
}
pub trait Functor {
type W<T: ?Sized + Trait>: ?Sized + Trait;
fn pure<A: ?Sized + Trait>(_: impl Impl<A>) -> impl Impl<Self::W<A>>;
fn map<A: ?Sized + Trait, F: TraitFn<A>>(
_: impl Impl<Self::W<A>>,
_: F,
) -> impl Impl<Self::W<F::Out>>;
}
pub struct Verbatim;
impl Functor for Verbatim {
type W<T: ?Sized + Trait> = T;
fn pure<A: ?Sized + Trait>(a: impl Impl<A>) -> impl Impl<Self::W<A>> {
a
}
fn map<A: ?Sized + Trait, F: TraitFn<A>>(
a: impl Impl<Self::W<A>>,
f: F,
) -> impl Impl<Self::W<F::Out>> {
f.run(a)
}
}
pub trait Call<T: ?Sized + Trait> {
type Output: Impl<T>;
fn call(self) -> Self::Output;
}
impl<T: ?Sized + Trait, I: Impl<To<T>>> Call<T> for I {
type Output = I::Associated;
fn call(self) -> Self::Output {
I::method(self)
}
}
pub struct Lazy;
impl Functor for Lazy {
type W<T: ?Sized + Trait> = To<T>;
fn pure<A: ?Sized + Trait>(a: impl Impl<A>) -> impl Impl<Self::W<A>> {
|| a
}
fn map<A: ?Sized + Trait, F: TraitFn<A>>(
a: impl Impl<Self::W<A>>,
f: F,
) -> impl Impl<Self::W<F::Out>> {
|| f.run(a.call())
}
}
pub struct Composition<Uo, Ui>(Uo, Ui);
impl<Uo: Functor, Ui: Functor> Functor for Composition<Ui, Uo> {
type W<T: ?Sized + Trait> = Uo::W<Ui::W<T>>;
fn pure<A: ?Sized + Trait>(a: impl Impl<A>) -> impl Impl<Self::W<A>> {
Uo::pure(Ui::pure(a))
}
fn map<A: ?Sized + Trait, F: TraitFn<A>>(
a: impl Impl<Self::W<A>>,
f: F,
) -> impl Impl<Self::W<F::Out>> {
struct Tmp<A: ?Sized, F, Uo, Ui>(F, PhantomData<(Uo, Ui, A)>);
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>;
fn run(self, a: impl Impl<Ui::W<A>>) -> impl Impl<Self::Out> {
Ui::map(a, self.0)
}
}
Uo::map(a, Tmp::<A, F, Uo, Ui>(f, PhantomData))
}
}
pub trait Into_<T: ?Sized + Trait> {
fn into_<A>(self) -> A
where
Self: Impl<Is<A, T>>,
{
Self::method(self)
}
}
impl<T: ?Sized + Trait, I> Into_<T> for I {}
impl<A, B, F: FnOnce(A) -> B, T: ?Sized + Trait> TraitFn<Is<A, T>> for F {
type Out = Is<B, Empty>;
fn run(self, a: impl Impl<Is<A, T>>) -> impl Impl<Self::Out> {
self(a.into_())
}
}
#[cfg(test)]
fn generic_test<U: Functor>() -> impl Impl<U::W<Is<i32, Empty>>> {
let x = U::pure::<Is<_, Empty>>(5);
let x = U::map(x, |x| x + 1);
let x = U::map(x, |x| x + 1);
let x = U::map(x, |x| x + 1);
let x = U::map(x, |x| x + 1);
U::map(x, |x| x + 1)
}
#[test]
fn doubly_lazy() {
type U = Composition<Lazy, Lazy>;
let x = generic_test::<U>();
let x = x.call().call().into_::<i32>();
assert_eq!(x, 10);
}
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>;
}
impl<T: ?Sized + Trait, Output: Impl<T>, F: Future<Output = Output>> Impl<FutureTo<T>> for F {
type Associated = F::Output;
fn method<'out: 'tmp, 'tmp>(
(this, cx): <FutureTo<T> as Trait>::In<'out, 'tmp, Self>,
) -> <FutureTo<T> as Trait>::Out<'out, Self::Associated>
where
Self: 'tmp,
{
this.poll(cx)
}
}
#[pin_project]
struct TraitFuture<F, T: ?Sized>(#[pin] F, PhantomData<T>);
impl<T: ?Sized + Trait, F: Impl<FutureTo<T>>> Future for TraitFuture<F, T> {
type Output = F::Associated;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
F::method((self.project().0, cx))
}
}
pub trait IntoFuture_<T: ?Sized + Trait>: Impl<FutureTo<T>> {
fn into_future_(self) -> impl Future<Output = Self::Associated> {
TraitFuture(self, PhantomData)
}
}
impl<T: ?Sized + Trait, I: Impl<FutureTo<T>>> IntoFuture_<T> for I {}
pub struct Futures;
impl Functor for Futures {
type W<T: ?Sized + Trait> = FutureTo<T>;
fn pure<A: ?Sized + Trait>(a: impl Impl<A>) -> impl Impl<Self::W<A>> {
async { a }
}
fn map<A: ?Sized + Trait, F: TraitFn<A>>(
a: impl Impl<Self::W<A>>,
f: F,
) -> impl Impl<Self::W<F::Out>> {
async { f.run(a.into_future_().await) }
}
}
#[test]
fn with_futures() {
type U = Futures;
let x = generic_test::<U>();
let x = futures::executor::block_on(x.into_future_()).into_::<i32>();
assert_eq!(x, 10);
}