From 829640804418ede6f1baa0aa0101899941a7212e Mon Sep 17 00:00:00 2001 From: d-plaindoux Date: Sun, 17 Sep 2023 00:39:43 +0200 Subject: [PATCH] Generic join and specific bind + Reader - Bind - bind and Monad --- src/specs/bind.rs | 9 ++++----- src/standard/either.rs | 11 +++++++---- src/standard/identity.rs | 7 +++++-- src/standard/option.rs | 9 ++++++--- src/standard/reader.rs | 27 ++++++++++++++++++++++++--- src/standard/result.rs | 9 ++++++--- src/standard/vec.rs | 4 ---- 7 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/specs/bind.rs b/src/specs/bind.rs index bd9f84f..f541eef 100644 --- a/src/specs/bind.rs +++ b/src/specs/bind.rs @@ -4,14 +4,13 @@ pub trait Bind<'a>: Applicative<'a> where Self: 'a, { - fn join(mma: Self::T>) -> Self::T; + fn join(mma: Self::T>) -> Self::T { + Self::bind(mma, |e| e) + } fn bind(ma: Self::T, mf: BIND) -> Self::T where - BIND: Fn(A) -> Self::T + 'a, - { - Self::join(Self::map(mf, ma)) - } + BIND: Fn(A) -> Self::T + 'a; } pub mod infix { diff --git a/src/standard/either.rs b/src/standard/either.rs index b1c39bb..20a4c6a 100644 --- a/src/standard/either.rs +++ b/src/standard/either.rs @@ -49,10 +49,13 @@ impl<'a, E> Applicative<'a> for EitherK { } impl<'a, E: 'a> Bind<'a> for EitherK { - fn join(mma: Self::T>) -> Self::T { - match mma { - Left(ma) => Left(ma), - Right(r) => r, + fn bind(ma: Self::T, f: BIND) -> Self::T + where + BIND: Fn(A) -> Self::T + 'a, + { + match ma { + Left(a) => Left(a), + Right(r) => f(r), } } } diff --git a/src/standard/identity.rs b/src/standard/identity.rs index c776bcc..bf0c93f 100644 --- a/src/standard/identity.rs +++ b/src/standard/identity.rs @@ -37,8 +37,11 @@ impl<'a> Applicative<'a> for IdentityK { } impl<'a> Bind<'a> for IdentityK { - fn join(mma: Self::T>) -> Self::T { - mma.value + fn bind(ma: Self::T, f: BIND) -> Self::T + where + BIND: Fn(A) -> Self::T + 'a, + { + f(ma.value) } } diff --git a/src/standard/option.rs b/src/standard/option.rs index ee184bb..73853cd 100644 --- a/src/standard/option.rs +++ b/src/standard/option.rs @@ -36,9 +36,12 @@ impl<'a> Applicative<'a> for OptionK { } impl<'a> Bind<'a> for OptionK { - fn join(mma: Self::T>) -> Self::T { - match mma { - Some(ma) => ma, + fn bind(ma: Self::T, f: BIND) -> Self::T + where + BIND: Fn(A) -> Self::T + 'a, + { + match ma { + Some(a) => f(a), None => None, } } diff --git a/src/standard/reader.rs b/src/standard/reader.rs index fe1a4cf..62f2928 100644 --- a/src/standard/reader.rs +++ b/src/standard/reader.rs @@ -2,6 +2,7 @@ use crate::core::hkp::HKP; use crate::specs::applicative::Applicative; use crate::specs::bind::Bind; use crate::specs::functor::Functor; +use crate::specs::monad::Monad; use std::marker::PhantomData; pub struct Reader<'a, E, F: HKP<'a>, A: 'a>(Box F::T + 'a>, PhantomData); @@ -23,9 +24,10 @@ impl<'e, E, F: Functor<'e> + 'e> Functor<'e> for ReaderK<'e, E, F> { } } -impl<'e, E: Clone, F: Applicative<'e> + 'e> Applicative<'e> for ReaderK<'e, E, F> { +impl<'e, E: Copy, F: Applicative<'e> + 'e> Applicative<'e> for ReaderK<'e, E, F> { fn pure(a: A) -> Self::T { - Reader(Box::new(|_| F::pure(a)), PhantomData) + let run = |_| F::pure(a); + Reader(Box::new(run), PhantomData) } fn apply(mf: Self::T, ma: Self::T) -> Self::T @@ -35,7 +37,26 @@ impl<'e, E: Clone, F: Applicative<'e> + 'e> Applicative<'e> for ReaderK<'e, E, F { let Reader(vf, _) = mf; let Reader(va, _) = ma; - let run = |e: E| F::apply(vf(e.clone()), va(e)); + let run = |e: E| F::apply(vf(e), va(e)); + Reader(Box::new(run), PhantomData) + } +} + +impl<'e, E: Copy, F: Bind<'e> + 'e> Bind<'e> for ReaderK<'e, E, F> { + fn bind(ma: Self::T, f: BIND) -> Self::T + where + BIND: Fn(A) -> Self::T + 'e, + { + let Reader(va, _) = ma; + let run = move |e1: E| { + F::bind(va(e1), move |e2: A| { + let Reader(v, _) = f(e2); + v(e1) + }) + }; + Reader(Box::new(run), PhantomData) } } + +impl<'e, E: Copy, F: Bind<'e> + 'e> Monad<'e> for ReaderK<'e, E, F> {} diff --git a/src/standard/result.rs b/src/standard/result.rs index a6cc3e5..1013083 100644 --- a/src/standard/result.rs +++ b/src/standard/result.rs @@ -40,9 +40,12 @@ impl<'a, E> Applicative<'a> for ResultK { } impl<'a, E: 'a> Bind<'a> for ResultK { - fn join(mma: Self::T>) -> Self::T { - match mma { - Ok(ma) => ma, + fn bind(ma: Self::T, f: BIND) -> Self::T + where + BIND: Fn(A) -> Self::T + 'a, + { + match ma { + Ok(a) => f(a), Err(e) => Err(e), } } diff --git a/src/standard/vec.rs b/src/standard/vec.rs index c5593a8..0c679cb 100644 --- a/src/standard/vec.rs +++ b/src/standard/vec.rs @@ -35,10 +35,6 @@ impl<'a> Applicative<'a> for VecK { } impl<'a> Bind<'a> for VecK { - fn join(mma: Self::T>) -> Self::T { - mma.into_iter().flatten().collect() - } - fn bind(ma: Self::T, mf: BIND) -> Self::T where BIND: Fn(A) -> Self::T + 'a,