ApplicativeSeq+ApplicativeLA2 lift lifetime

This commit is contained in:
AF 2023-05-26 09:21:09 +00:00
parent 73f8a2f356
commit 7f69b10e2e
12 changed files with 78 additions and 134 deletions

View File

@ -127,26 +127,22 @@ pub trait Pure: Functor {
} }
/// Part of [`Applicative`] responsible for Haskell's sequential application `<*>`. /// Part of [`Applicative`] responsible for Haskell's sequential application `<*>`.
pub trait ApplicativeSeq: Functor { pub trait ApplicativeSeq<'a>: 'a + Functor {
/// Equivalent of Haskell's `<*>`. /// Equivalent of Haskell's `<*>`.
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>;
where
Self: 'a;
} }
/// Part of [`Applicative`] responsible for Haskell's result combination `listA2`. /// Part of [`Applicative`] responsible for Haskell's result combination `listA2`.
pub trait ApplicativeLA2: Functor { pub trait ApplicativeLA2<'a>: 'a + Functor {
/// Equivalent of Haskell's `listA2`. /// Equivalent of Haskell's `listA2`.
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,
) -> Self::F<'a, C> ) -> Self::F<'a, C>;
where
Self: 'a;
} }
/// Part of [`Applicative`] responsible for Rust-style result combination, specifically for tuples. /// Part of [`Applicative`] responsible for Rust-style result combination, specifically for tuples.
@ -160,7 +156,7 @@ pub trait ApplicativeTuple<'a>: 'a + Functor {
/// ///
/// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Applicative.html> /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Applicative.html>
pub trait Applicative<'a>: pub trait Applicative<'a>:
Pure + ApplicativeSeq + ApplicativeLA2 + ApplicativeTuple<'a> + ApplicativeSelect<'a> Pure + ApplicativeSeq<'a> + ApplicativeLA2<'a> + ApplicativeTuple<'a> + ApplicativeSelect<'a>
{ {
/// Equivalent of Haskell's `*>`/`>>`. /// Equivalent of Haskell's `*>`/`>>`.
fn discard_first<A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { fn discard_first<A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> {

View File

@ -16,65 +16,35 @@ pub fn bind<'a, T: Monad<'a>, A: 'a, B: 'a>(
move |fa| T::bind(fa, f) move |fa| T::bind(fa, f)
} }
pub trait ApplicativeLA2ViaSeq: ApplicativeSeq { pub trait ApplicativeLA2ViaSeq<'a>: ApplicativeSeq<'a> {
fn _la2_via_seq<'a, A: 'a, B: 'a, C: 'a>( fn _la2_via_seq<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,
) -> Self::F<'a, C> ) -> Self::F<'a, C> {
where
Self: 'a;
}
impl<T: ApplicativeSeq> ApplicativeLA2ViaSeq for T {
fn _la2_via_seq<'a, A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>,
fb: Self::F<'a, B>,
) -> Self::F<'a, C>
where
Self: 'a,
{
Self::seq(Self::fmap(|a| |b| f(a, b), fa), fb) Self::seq(Self::fmap(|a| |b| f(a, b), fa), fb)
} }
} }
pub trait ApplicativeSeqViaLA2: ApplicativeLA2 { impl<'a, T: ApplicativeSeq<'a>> ApplicativeLA2ViaSeq<'a> for T {}
fn _seq_via_la2<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>,
) -> Self::F<'a, B>
where
Self: 'a;
}
impl<T: ApplicativeLA2> ApplicativeSeqViaLA2 for T { pub trait ApplicativeSeqViaLA2<'a>: ApplicativeLA2<'a> {
fn _seq_via_la2<'a, A: 'a, B: 'a>( fn _seq_via_la2<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> ) -> Self::F<'a, B> {
where
Self: 'a,
{
Self::la2(|f, a| f(a), ff, fa) Self::la2(|f, a| f(a), ff, fa)
} }
} }
pub trait ApplicativeTupleViaLA2: ApplicativeLA2 { impl<'a, T: ApplicativeLA2<'a>> ApplicativeSeqViaLA2<'a> for T {}
fn _tuple_via_la2<'a, A: 'a, B: 'a>(
fab: (Self::F<'a, A>, Self::F<'a, B>),
) -> Self::F<'a, (A, B)>
where
Self: 'a;
}
impl<T: ApplicativeLA2> ApplicativeTupleViaLA2 for T { pub trait ApplicativeTupleViaLA2<'a>: ApplicativeLA2<'a> {
fn _tuple_via_la2<'a, A: 'a, B: 'a>( fn _tuple_via_la2<A: 'a, B: 'a>(
(fa, fb): (Self::F<'a, A>, Self::F<'a, B>), (fa, fb): (Self::F<'a, A>, Self::F<'a, B>),
) -> Self::F<'a, (A, B)> ) -> Self::F<'a, (A, B)> {
where
Self: 'a,
{
Self::la2(|a, b| (a, b), fa, fb) Self::la2(|a, b| (a, b), fa, fb)
} }
} }
impl<'a, T: ApplicativeLA2<'a>> ApplicativeTupleViaLA2<'a> for T {}

View File

@ -38,27 +38,25 @@ impl<U: Pure, V: Pure> Pure for CompositionInstance<U, V> {
} }
} }
impl<U: ApplicativeLA2, V: ApplicativeSeq> ApplicativeSeq for CompositionInstance<U, V> { impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeSeq<'a>> ApplicativeSeq<'a>
fn seq<'a, A: 'a, B: 'a>( for CompositionInstance<U, V>
{
fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> ) -> Self::F<'a, B> {
where
Self: 'a,
{
U::la2(|uf, ua| V::seq(uf, ua), ff, fa) U::la2(|uf, ua| V::seq(uf, ua), ff, fa)
} }
} }
impl<U: ApplicativeLA2, V: ApplicativeLA2> ApplicativeLA2 for CompositionInstance<U, V> { impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeLA2<'a>> ApplicativeLA2<'a>
fn la2<'a, A: 'a, B: 'a, C: 'a>( for CompositionInstance<U, V>
{
fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,
) -> Self::F<'a, C> ) -> Self::F<'a, C> {
where
Self: 'a,
{
U::la2(|ua, ub| V::la2(f, ua, ub), fa, fb) U::la2(|ua, ub| V::la2(f, ua, ub), fa, fb)
} }
} }

View File

@ -67,8 +67,8 @@ impl<E: Effect> Pure for EffectInstance<E> {
} }
} }
impl<E: Effect> ApplicativeSeq for EffectInstance<E> { impl<'a, E: 'a + Effect> ApplicativeSeq<'a> for EffectInstance<E> {
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
@ -82,8 +82,8 @@ impl<E: Effect> ApplicativeSeq for EffectInstance<E> {
} }
} }
impl<E: Effect> ApplicativeLA2 for EffectInstance<E> { impl<'a, E: 'a + Effect> ApplicativeLA2<'a> for EffectInstance<E> {
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,

View File

@ -38,8 +38,8 @@ impl Pure for FutureInstance {
} }
} }
impl ApplicativeSeq for FutureInstance { impl<'a> ApplicativeSeq<'a> for FutureInstance {
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> { ) -> Self::F<'a, B> {
@ -50,8 +50,8 @@ impl ApplicativeSeq for FutureInstance {
} }
} }
impl ApplicativeLA2 for FutureInstance { impl<'a> ApplicativeLA2<'a> for FutureInstance {
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,

View File

@ -40,8 +40,8 @@ impl Pure for LazyInstance {
} }
} }
impl ApplicativeSeq for LazyInstance { impl<'a> ApplicativeSeq<'a> for LazyInstance {
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> { ) -> Self::F<'a, B> {
@ -49,8 +49,8 @@ impl ApplicativeSeq for LazyInstance {
} }
} }
impl ApplicativeLA2 for LazyInstance { impl<'a> ApplicativeLA2<'a> for LazyInstance {
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,

View File

@ -44,8 +44,8 @@ impl Pure for OptionInstance {
} }
} }
impl ApplicativeSeq for OptionInstance { impl<'a> ApplicativeSeq<'a> for OptionInstance {
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> { ) -> Self::F<'a, B> {
@ -53,8 +53,8 @@ impl ApplicativeSeq for OptionInstance {
} }
} }
impl ApplicativeLA2 for OptionInstance { impl<'a> ApplicativeLA2<'a> for OptionInstance {
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,

View File

@ -50,27 +50,25 @@ impl<T: Pure, O: DeriveApplicative> Pure for OverloadInstance<T, O> {
} }
} }
impl<T: ApplicativeSeq, O: DeriveApplicative> ApplicativeSeq for OverloadInstance<T, O> { impl<'a, T: ApplicativeSeq<'a>, O: 'a + DeriveApplicative> ApplicativeSeq<'a>
fn seq<'a, A: 'a, B: 'a>( for OverloadInstance<T, O>
{
fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> ) -> Self::F<'a, B> {
where
Self: 'a,
{
T::seq(ff, fa) T::seq(ff, fa)
} }
} }
impl<T: ApplicativeLA2, O: DeriveApplicative> ApplicativeLA2 for OverloadInstance<T, O> { impl<'a, T: ApplicativeLA2<'a>, O: 'a + DeriveApplicative> ApplicativeLA2<'a>
fn la2<'a, A: 'a, B: 'a, C: 'a>( for OverloadInstance<T, O>
{
fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,
) -> Self::F<'a, C> ) -> Self::F<'a, C> {
where
Self: 'a,
{
T::la2(f, fa, fb) T::la2(f, fa, fb)
} }
} }

View File

@ -50,27 +50,21 @@ impl<E> Pure for ResultInstance<E> {
} }
} }
impl<E> ApplicativeSeq for ResultInstance<E> { impl<'a, E: 'a> ApplicativeSeq<'a> for ResultInstance<E> {
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> ) -> Self::F<'a, B> {
where
Self: 'a,
{
Self::pure(ff?(fa?)) Self::pure(ff?(fa?))
} }
} }
impl<E> ApplicativeLA2 for ResultInstance<E> { impl<'a, E: 'a> ApplicativeLA2<'a> for ResultInstance<E> {
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,
) -> Self::F<'a, C> ) -> Self::F<'a, C> {
where
Self: 'a,
{
Self::pure(f(fa?, fb?)) Self::pure(f(fa?, fb?))
} }
} }

View File

@ -32,8 +32,8 @@ impl Pure for SoloInstance {
} }
} }
impl ApplicativeSeq for SoloInstance { impl<'a> ApplicativeSeq<'a> for SoloInstance {
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> { ) -> Self::F<'a, B> {
@ -41,8 +41,8 @@ impl ApplicativeSeq for SoloInstance {
} }
} }
impl ApplicativeLA2 for SoloInstance { impl<'a> ApplicativeLA2<'a> for SoloInstance {
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,

View File

@ -153,27 +153,21 @@ impl Pure for StacklessInstance {
} }
} }
impl ApplicativeSeq for StacklessInstance { impl<'a> ApplicativeSeq<'a> for StacklessInstance {
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> ) -> Self::F<'a, B> {
where
Self: 'a,
{
ff.bind(|f| fa.map(f)) ff.bind(|f| fa.map(f))
} }
} }
impl ApplicativeLA2 for StacklessInstance { impl<'a> ApplicativeLA2<'a> for StacklessInstance {
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,
) -> Self::F<'a, C> ) -> Self::F<'a, C> {
where
Self: 'a,
{
Self::_la2_via_seq(f, fa, fb) Self::_la2_via_seq(f, fa, fb)
} }
} }

View File

@ -42,14 +42,11 @@ impl<E> Pure for TryFutureInstance<E> {
} }
} }
impl<E> ApplicativeSeq for TryFutureInstance<E> { impl<'a, E: 'a> ApplicativeSeq<'a> for TryFutureInstance<E> {
fn seq<'a, A: 'a, B: 'a>( fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
) -> Self::F<'a, B> ) -> Self::F<'a, B> {
where
Self: 'a,
{
Box::pin(async { Box::pin(async {
let (f, a) = try_join!(ff, fa)?; let (f, a) = try_join!(ff, fa)?;
Ok(f(a)) Ok(f(a))
@ -57,15 +54,12 @@ impl<E> ApplicativeSeq for TryFutureInstance<E> {
} }
} }
impl<E> ApplicativeLA2 for TryFutureInstance<E> { impl<'a, E: 'a> ApplicativeLA2<'a> for TryFutureInstance<E> {
fn la2<'a, A: 'a, B: 'a, C: 'a>( fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C, f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>, fa: Self::F<'a, A>,
fb: Self::F<'a, B>, fb: Self::F<'a, B>,
) -> Self::F<'a, C> ) -> Self::F<'a, C> {
where
Self: 'a,
{
Box::pin(async { Box::pin(async {
let (a, b) = try_join!(fa, fb)?; let (a, b) = try_join!(fa, fb)?;
Ok(f(a, b)) Ok(f(a, b))