From 887807c740d67baa633235f8ab754f1749236513 Mon Sep 17 00:00:00 2001 From: timofey Date: Mon, 13 May 2024 21:49:57 +0300 Subject: [PATCH] Applicative --- src/model_03.rs | 106 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 9 deletions(-) diff --git a/src/model_03.rs b/src/model_03.rs index 25b1e81..b0ed681 100644 --- a/src/model_03.rs +++ b/src/model_03.rs @@ -4,7 +4,7 @@ use std::{ task::{Context, Poll}, }; -use futures::Future; +use futures::{join, Future}; use pin_project::pin_project; pub trait Trait { @@ -87,6 +87,11 @@ pub trait TraitFn { fn run(self, _: impl Impl) -> impl Impl; } +pub trait TraitFn2 { + type Out: ?Sized + Trait; + fn run(self, _: impl Impl, _: impl Impl) -> impl Impl; +} + pub trait Functor { type W: ?Sized + Trait; fn pure(_: impl Impl) -> impl Impl>; @@ -96,6 +101,18 @@ pub trait Functor { ) -> impl Impl>; } +pub trait Applicative: Functor { + fn map2>( + _: impl Impl>, + _: impl Impl>, + _: F, + ) -> impl Impl>; +} + +pub trait Monad: Functor { + fn flatten(_: impl Impl>>) -> impl Impl>; +} + pub struct Verbatim; impl Functor for Verbatim { @@ -113,6 +130,22 @@ impl Functor for Verbatim { } } +impl Applicative for Verbatim { + fn map2>( + a: impl Impl>, + b: impl Impl>, + f: F, + ) -> impl Impl> { + f.run(a, b) + } +} + +impl Monad for Verbatim { + fn flatten(a: impl Impl>>) -> impl Impl> { + a + } +} + pub trait Call { type Output: Impl; fn call(self) -> Self::Output; @@ -143,9 +176,25 @@ impl Functor for Lazy { } } +impl Applicative for Lazy { + fn map2>( + a: impl Impl>, + b: impl Impl>, + f: F, + ) -> impl Impl> { + || f.run(a.call(), b.call()) + } +} + +impl Monad for Lazy { + fn flatten(a: impl Impl>>) -> impl Impl> { + || a.call().call() + } +} + pub struct Composition(Uo, Ui); -impl Functor for Composition { +impl Functor for Composition { type W = Uo::W>; fn pure(a: impl Impl) -> impl Impl> { @@ -156,17 +205,38 @@ impl Functor for Composition { a: impl Impl>, f: F, ) -> impl Impl> { - struct Tmp(F, PhantomData<(Uo, Ui, A)>); - impl, Uo: Functor, Ui: Functor> TraitFn> - for Tmp - { + struct Tmp(F, PhantomData<(Ui, A)>); + impl, Ui: Functor> TraitFn> for Tmp { type Out = Ui::W; fn run(self, a: impl Impl>) -> impl Impl { Ui::map(a, self.0) } } - Uo::map(a, Tmp::(f, PhantomData)) + Uo::map(a, Tmp::(f, PhantomData)) + } +} + +impl Applicative for Composition { + fn map2>( + a: impl Impl>, + b: impl Impl>, + f: F, + ) -> impl Impl> { + struct Tmp( + F, + PhantomData<(Ui, PhantomData, PhantomData)>, + ); + impl, Ui: Applicative> + TraitFn2, Ui::W> for Tmp + { + type Out = Ui::W; + + fn run(self, a: impl Impl>, b: impl Impl>) -> impl Impl { + Ui::map2(a, b, self.0) + } + } + Uo::map2(a, b, Tmp::(f, PhantomData)) } } @@ -264,6 +334,25 @@ impl Functor for Futures { } } +impl Applicative for Futures { + fn map2>( + a: impl Impl>, + b: impl Impl>, + f: F, + ) -> impl Impl> { + async { + let (a, b) = join!(a.into_future_(), b.into_future_()); + f.run(a, b) + } + } +} + +impl Monad for Futures { + fn flatten(a: impl Impl>>) -> impl Impl> { + async { a.into_future_().await.into_future_().await } + } +} + #[test] fn with_futures() { type U = Futures; @@ -276,7 +365,6 @@ fn with_futures() { fn doubly_futures() { type U = Composition; let x = generic_test::(); - let x = futures::executor::block_on(async { x.into_future_().await.into_future_().await }) - .into_::(); + let x = futures::executor::block_on(Futures::flatten(x).into_future_()).into_::(); assert_eq!(x, 10); }