From dde3af2386f3ca0bde5282e592a6a8243f87e0e3 Mon Sep 17 00:00:00 2001 From: timofey Date: Fri, 26 May 2023 08:58:28 +0000 Subject: [PATCH] `Applicative` lift lifetime --- src/func.rs | 16 +++++----------- src/func/instances/composition.rs | 12 +++--------- src/func/instances/effect.rs | 12 +++--------- src/func/instances/future.rs | 6 +++--- src/func/instances/lazy.rs | 6 +++--- src/func/instances/option.rs | 6 +++--- src/func/instances/overload.rs | 12 +++--------- src/func/instances/result.rs | 12 +++--------- src/func/instances/solo.rs | 6 +++--- src/func/instances/stackless.rs | 12 +++--------- src/func/instances/tryfuture.rs | 12 +++--------- src/func/test_suite.rs | 2 +- src/func/tests.rs | 14 +++++++------- 13 files changed, 43 insertions(+), 85 deletions(-) diff --git a/src/func.rs b/src/func.rs index 01692a7..e01dcb3 100644 --- a/src/func.rs +++ b/src/func.rs @@ -161,22 +161,16 @@ pub trait ApplicativeTuple: Functor { /// Split into [`Pure`], [`ApplicativeSeq`], [`ApplicativeLA2`] and [`ApplicativeTuple`] due to Rust limitations. /// /// -pub trait Applicative: - Pure + ApplicativeSeq + ApplicativeLA2 + ApplicativeTuple + ApplicativeSelect +pub trait Applicative<'a>: + 'a + Pure + ApplicativeSeq + ApplicativeLA2 + ApplicativeTuple + ApplicativeSelect { /// Equivalent of Haskell's `*>`/`>>`. - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> - where - Self: 'a, - { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { Self::seq(Self::replace(fa, |b| b), fb) } /// Equivalent of Haskell's `<*`. - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> - where - Self: 'a, - { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { Self::la2(|a, _| a, fa, fb) } } @@ -184,7 +178,7 @@ pub trait Applicative: /// Equivalent of Haskell's `Monad`. /// /// -pub trait Monad<'a>: 'a + Applicative { +pub trait Monad<'a>: Applicative<'a> { /// Equivalent of Haskell's `>==`. /// Due to Rust limitations, it's not a `function->function` conversion. /// For that see [`derivations::bind`]. diff --git a/src/func/instances/composition.rs b/src/func/instances/composition.rs index b478b18..86f47ab 100644 --- a/src/func/instances/composition.rs +++ b/src/func/instances/composition.rs @@ -90,18 +90,12 @@ impl ApplicativeSelect for CompositionInstance } } -impl Applicative for CompositionInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> - where - Self: 'a, - { +impl<'a, U: Applicative<'a>, V: Applicative<'a>> Applicative<'a> for CompositionInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { U::la2(|ua, ub| V::discard_first(ua, ub), fa, fb) } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> - where - Self: 'a, - { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { U::la2(|ua, ub| V::discard_second(ua, ub), fa, fb) } } diff --git a/src/func/instances/effect.rs b/src/func/instances/effect.rs index 20ce3a9..6b53cf2 100644 --- a/src/func/instances/effect.rs +++ b/src/func/instances/effect.rs @@ -112,11 +112,8 @@ impl ApplicativeTuple for EffectInstance { impl ApplicativeSelect for EffectInstance {} -impl Applicative for EffectInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> - where - Self: 'a, - { +impl<'a, E: 'a + Effect> Applicative<'a> for EffectInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { drop(fa.value); WithEffect { value: fb.value, @@ -124,10 +121,7 @@ impl Applicative for EffectInstance { } } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> - where - Self: 'a, - { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { drop(fb.value); WithEffect { value: fa.value, diff --git a/src/func/instances/future.rs b/src/func/instances/future.rs index 2fe9153..5c5f374 100644 --- a/src/func/instances/future.rs +++ b/src/func/instances/future.rs @@ -89,12 +89,12 @@ impl ApplicativeSelect for FutureInstance { } } -impl Applicative for FutureInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { +impl<'a> Applicative<'a> for FutureInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { Box::pin(async { join!(fa, fb).1 }) } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { Box::pin(async { join!(fa, fb).0 }) } } diff --git a/src/func/instances/lazy.rs b/src/func/instances/lazy.rs index 2f791f5..b37a753 100644 --- a/src/func/instances/lazy.rs +++ b/src/func/instances/lazy.rs @@ -70,13 +70,13 @@ impl ApplicativeTuple for LazyInstance { impl ApplicativeSelect for LazyInstance {} -impl Applicative for LazyInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { +impl<'a> Applicative<'a> for LazyInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { drop(fa); fb } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { drop(fb); fa } diff --git a/src/func/instances/option.rs b/src/func/instances/option.rs index fd3b27f..fbcaae5 100644 --- a/src/func/instances/option.rs +++ b/src/func/instances/option.rs @@ -74,13 +74,13 @@ impl ApplicativeTuple for OptionInstance { impl ApplicativeSelect for OptionInstance {} -impl Applicative for OptionInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { +impl<'a> Applicative<'a> for OptionInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { fa?; fb } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { fb?; fa } diff --git a/src/func/instances/overload.rs b/src/func/instances/overload.rs index 99daa6a..f737963 100644 --- a/src/func/instances/overload.rs +++ b/src/func/instances/overload.rs @@ -86,18 +86,12 @@ impl ApplicativeTuple for OverloadIns impl ApplicativeSelect for OverloadInstance {} -impl Applicative for OverloadInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> - where - Self: 'a, - { +impl<'a, T: Applicative<'a>, O: 'a + DeriveApplicative> Applicative<'a> for OverloadInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { T::discard_first(fa, fb) } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> - where - Self: 'a, - { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { T::discard_second(fa, fb) } } diff --git a/src/func/instances/result.rs b/src/func/instances/result.rs index 6371bb4..034f248 100644 --- a/src/func/instances/result.rs +++ b/src/func/instances/result.rs @@ -86,19 +86,13 @@ impl ApplicativeTuple for ResultInstance { impl ApplicativeSelect for ResultInstance {} -impl Applicative for ResultInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> - where - Self: 'a, - { +impl<'a, E: 'a> Applicative<'a> for ResultInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { fa?; fb } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> - where - Self: 'a, - { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { fb?; fa } diff --git a/src/func/instances/solo.rs b/src/func/instances/solo.rs index c8d6051..7758681 100644 --- a/src/func/instances/solo.rs +++ b/src/func/instances/solo.rs @@ -62,13 +62,13 @@ impl ApplicativeTuple for SoloInstance { impl ApplicativeSelect for SoloInstance {} -impl Applicative for SoloInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { +impl<'a> Applicative<'a> for SoloInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { drop(fa); fb } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { drop(fb); fa } diff --git a/src/func/instances/stackless.rs b/src/func/instances/stackless.rs index 66a500e..2a3915d 100644 --- a/src/func/instances/stackless.rs +++ b/src/func/instances/stackless.rs @@ -189,11 +189,8 @@ impl ApplicativeTuple for StacklessInstance { impl ApplicativeSelect for StacklessInstance {} -impl Applicative for StacklessInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> - where - Self: 'a, - { +impl<'a> Applicative<'a> for StacklessInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { Stackless(Box::new(|takesb| { Some(EvalTree::Composite( Box::new(EvalTree::Atom(Box::new(|| fa.call(drop)))), @@ -202,10 +199,7 @@ impl Applicative for StacklessInstance { })) } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> - where - Self: 'a, - { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { Stackless(Box::new(|takesa| { Some(EvalTree::Composite( Box::new(EvalTree::Atom(Box::new(|| fa.0(takesa)))), diff --git a/src/func/instances/tryfuture.rs b/src/func/instances/tryfuture.rs index dabf349..d09d671 100644 --- a/src/func/instances/tryfuture.rs +++ b/src/func/instances/tryfuture.rs @@ -101,18 +101,12 @@ impl ApplicativeSelect for TryFutureInstance { } } -impl Applicative for TryFutureInstance { - fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> - where - Self: 'a, - { +impl<'a, E: 'a> Applicative<'a> for TryFutureInstance { + fn discard_first(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { Box::pin(async { Ok(try_join!(fa, fb)?.1) }) } - fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> - where - Self: 'a, - { + fn discard_second(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { Box::pin(async { Ok(try_join!(fa, fb)?.0) }) } } diff --git a/src/func/test_suite.rs b/src/func/test_suite.rs index 3c86d21..b016277 100644 --- a/src/func/test_suite.rs +++ b/src/func/test_suite.rs @@ -19,7 +19,7 @@ pub fn functor_follows_laws() -> R { res } -pub fn applicative_follows_laws() -> R { +pub fn applicative_follows_laws<'a, T: Applicative<'a> + FunctorTestSuite>() -> R { let mut res = functor_follows_laws::(); T::sample(|pa| { res += seq_respects_identity::(|| pa(2)); diff --git a/src/func/tests.rs b/src/func/tests.rs index 2e9f1cb..f6c2253 100644 --- a/src/func/tests.rs +++ b/src/func/tests.rs @@ -115,7 +115,7 @@ pub fn fmap_respects_composition< ) } -pub fn seq_respects_identity<'a, T: 'a + Applicative + Eqr, A: 'a + Debug + PartialEq>( +pub fn seq_respects_identity<'a, T: Applicative<'a> + Eqr, A: 'a + Debug + PartialEq>( fa0: impl Fn() -> T::F<'a, A>, ) -> R { T::eqr( @@ -127,7 +127,7 @@ pub fn seq_respects_identity<'a, T: 'a + Applicative + Eqr, A: 'a + Debug + Part pub fn seq_respects_composition< 'a, - T: 'a + Applicative + Eqr, + T: Applicative<'a> + Eqr, A: 'a, B: 'a, C: 'a + Debug + PartialEq, @@ -151,7 +151,7 @@ pub fn seq_respects_composition< ) } -pub fn seq_is_homomorphic<'a, T: 'a + Applicative + Eqr, A: 'a, B: 'a + Debug + PartialEq>( +pub fn seq_is_homomorphic<'a, T: Applicative<'a> + Eqr, A: 'a, B: 'a + Debug + PartialEq>( f: impl 'a + Fn(A) -> B, a0: impl Fn() -> A, ) -> R { @@ -164,7 +164,7 @@ pub fn seq_is_homomorphic<'a, T: 'a + Applicative + Eqr, A: 'a, B: 'a + Debug + pub fn seq_respects_interchange< 'a, - T: 'a + Applicative + Eqr, + T: Applicative<'a> + Eqr, A: 'a, B: 'a + Debug + PartialEq, F: 'a + Fn(A) -> B, @@ -181,7 +181,7 @@ pub fn seq_respects_interchange< pub fn seq_can_be_expressed_via_la2< 'a, - T: 'a + Applicative + Eqr, + T: Applicative<'a> + Eqr, A: 'a, B: 'a + Debug + PartialEq, F: 'a + Fn(A) -> B, @@ -198,7 +198,7 @@ pub fn seq_can_be_expressed_via_la2< pub fn fmap_can_be_expressed_via_seq< 'a, - T: 'a + Applicative + Eqr, + T: Applicative<'a> + Eqr, A: 'a, B: 'a + Debug + PartialEq, >( @@ -214,7 +214,7 @@ pub fn fmap_can_be_expressed_via_seq< pub fn discard_can_be_expressed_via_seq_or_la2< 'a, - T: 'a + Applicative + Eqr, + T: Applicative<'a> + Eqr, A: 'a, B: 'a + Debug + PartialEq, >(