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 `<*>`.
pub trait ApplicativeSeq: Functor {
pub trait ApplicativeSeq<'a>: 'a + Functor {
/// 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>,
fa: Self::F<'a, A>,
) -> Self::F<'a, B>
where
Self: 'a;
) -> Self::F<'a, B>;
}
/// 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`.
fn la2<'a, A: 'a, B: 'a, C: 'a>(
fn la2<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::F<'a, C>;
}
/// 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>
pub trait Applicative<'a>:
Pure + ApplicativeSeq + ApplicativeLA2 + ApplicativeTuple<'a> + ApplicativeSelect<'a>
Pure + ApplicativeSeq<'a> + ApplicativeLA2<'a> + ApplicativeTuple<'a> + ApplicativeSelect<'a>
{
/// 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> {

View File

@ -16,65 +16,35 @@ pub fn bind<'a, T: Monad<'a>, A: 'a, B: 'a>(
move |fa| T::bind(fa, f)
}
pub trait ApplicativeLA2ViaSeq: ApplicativeSeq {
fn _la2_via_seq<'a, A: 'a, B: 'a, C: 'a>(
pub trait ApplicativeLA2ViaSeq<'a>: ApplicativeSeq<'a> {
fn _la2_via_seq<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;
}
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::F<'a, C> {
Self::seq(Self::fmap(|a| |b| f(a, b), fa), fb)
}
}
pub trait ApplicativeSeqViaLA2: ApplicativeLA2 {
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<'a, T: ApplicativeSeq<'a>> ApplicativeLA2ViaSeq<'a> for T {}
impl<T: ApplicativeLA2> ApplicativeSeqViaLA2 for T {
fn _seq_via_la2<'a, A: 'a, B: 'a>(
pub trait ApplicativeSeqViaLA2<'a>: ApplicativeLA2<'a> {
fn _seq_via_la2<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,
{
) -> Self::F<'a, B> {
Self::la2(|f, a| f(a), ff, fa)
}
}
pub trait ApplicativeTupleViaLA2: ApplicativeLA2 {
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<'a, T: ApplicativeLA2<'a>> ApplicativeSeqViaLA2<'a> for T {}
impl<T: ApplicativeLA2> ApplicativeTupleViaLA2 for T {
fn _tuple_via_la2<'a, A: 'a, B: 'a>(
pub trait ApplicativeTupleViaLA2<'a>: ApplicativeLA2<'a> {
fn _tuple_via_la2<A: 'a, B: 'a>(
(fa, fb): (Self::F<'a, A>, Self::F<'a, B>),
) -> Self::F<'a, (A, B)>
where
Self: 'a,
{
) -> Self::F<'a, (A, B)> {
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> {
fn seq<'a, A: 'a, B: 'a>(
impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeSeq<'a>> ApplicativeSeq<'a>
for CompositionInstance<U, V>
{
fn seq<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,
{
) -> Self::F<'a, B> {
U::la2(|uf, ua| V::seq(uf, ua), ff, fa)
}
}
impl<U: ApplicativeLA2, V: ApplicativeLA2> ApplicativeLA2 for CompositionInstance<U, V> {
fn la2<'a, A: 'a, B: 'a, C: 'a>(
impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeLA2<'a>> ApplicativeLA2<'a>
for CompositionInstance<U, V>
{
fn la2<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::F<'a, C> {
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> {
fn seq<'a, A: 'a, B: 'a>(
impl<'a, E: 'a + Effect> ApplicativeSeq<'a> for EffectInstance<E> {
fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>,
) -> Self::F<'a, B>
@ -82,8 +82,8 @@ impl<E: Effect> ApplicativeSeq for EffectInstance<E> {
}
}
impl<E: Effect> ApplicativeLA2 for EffectInstance<E> {
fn la2<'a, A: 'a, B: 'a, C: 'a>(
impl<'a, E: 'a + Effect> ApplicativeLA2<'a> for EffectInstance<E> {
fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>,
fb: Self::F<'a, B>,

View File

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

View File

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

View File

@ -44,8 +44,8 @@ impl Pure for OptionInstance {
}
}
impl ApplicativeSeq for OptionInstance {
fn seq<'a, A: 'a, B: 'a>(
impl<'a> ApplicativeSeq<'a> for OptionInstance {
fn seq<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>,
) -> Self::F<'a, B> {
@ -53,8 +53,8 @@ impl ApplicativeSeq for OptionInstance {
}
}
impl ApplicativeLA2 for OptionInstance {
fn la2<'a, A: 'a, B: 'a, C: 'a>(
impl<'a> ApplicativeLA2<'a> for OptionInstance {
fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>,
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> {
fn seq<'a, A: 'a, B: 'a>(
impl<'a, T: ApplicativeSeq<'a>, O: 'a + DeriveApplicative> ApplicativeSeq<'a>
for OverloadInstance<T, O>
{
fn seq<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,
{
) -> Self::F<'a, B> {
T::seq(ff, fa)
}
}
impl<T: ApplicativeLA2, O: DeriveApplicative> ApplicativeLA2 for OverloadInstance<T, O> {
fn la2<'a, A: 'a, B: 'a, C: 'a>(
impl<'a, T: ApplicativeLA2<'a>, O: 'a + DeriveApplicative> ApplicativeLA2<'a>
for OverloadInstance<T, O>
{
fn la2<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::F<'a, C> {
T::la2(f, fa, fb)
}
}

View File

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

View File

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

View File

@ -153,27 +153,21 @@ impl Pure for StacklessInstance {
}
}
impl ApplicativeSeq for StacklessInstance {
fn seq<'a, A: 'a, B: 'a>(
impl<'a> ApplicativeSeq<'a> for StacklessInstance {
fn seq<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,
{
) -> Self::F<'a, B> {
ff.bind(|f| fa.map(f))
}
}
impl ApplicativeLA2 for StacklessInstance {
fn la2<'a, A: 'a, B: 'a, C: 'a>(
impl<'a> ApplicativeLA2<'a> for StacklessInstance {
fn la2<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::F<'a, C> {
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> {
fn seq<'a, A: 'a, B: 'a>(
impl<'a, E: 'a> ApplicativeSeq<'a> for TryFutureInstance<E> {
fn seq<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,
{
) -> Self::F<'a, B> {
Box::pin(async {
let (f, a) = try_join!(ff, fa)?;
Ok(f(a))
@ -57,15 +54,12 @@ impl<E> ApplicativeSeq for TryFutureInstance<E> {
}
}
impl<E> ApplicativeLA2 for TryFutureInstance<E> {
fn la2<'a, A: 'a, B: 'a, C: 'a>(
impl<'a, E: 'a> ApplicativeLA2<'a> for TryFutureInstance<E> {
fn la2<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::F<'a, C> {
Box::pin(async {
let (a, b) = try_join!(fa, fb)?;
Ok(f(a, b))