Pure + LocalFunctor

This commit is contained in:
AF 2023-04-24 17:21:36 +00:00
parent e89e44d129
commit 1a5e9f15f3
10 changed files with 140 additions and 39 deletions

View File

@ -91,6 +91,14 @@ pub trait Functor: WeakFunctor {
}
}
/// Part of [`Applicative`] responsible for Haskell's value lifting, `pure`.
pub trait Pure: Functor {
/// Equivalent of Haskell's `pure`/`return`.
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A>
where
Self: 'a;
}
/// Part of [`Applicative`] responsible for Haskell's sequential application `<*>`.
pub trait ApplicativeSeq: Functor {
/// Equivalent of Haskell's `<*>`.
@ -123,13 +131,10 @@ pub trait ApplicativeTuple: Functor {
}
/// Equivalent of Haskell's `Applicative`.
/// Split into [`ApplicativeSeq`], [`ApplicativeLA2`] and [`ApplicativeTuple`] due to Rust limitations.
/// Split into [`Pure`], [`ApplicativeSeq`], [`ApplicativeLA2`] and [`ApplicativeTuple`] due to Rust limitations.
///
/// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Applicative.html>
pub trait Applicative: Functor + ApplicativeSeq + ApplicativeLA2 + ApplicativeTuple {
/// Equivalent of Haskell's `pure`/`return`.
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A>;
pub trait Applicative: Pure + ApplicativeSeq + ApplicativeLA2 + ApplicativeTuple {
/// 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
@ -214,3 +219,16 @@ pub trait Alternative: Applicative {
where
Self: 'a;
}
/// Represents wrapped results which are instantly available.
pub trait LocalFunctor: WeakFunctor {
/// Extract iteration state, if successful.
fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState<A, B>>) -> IState<A, Self::F<'a, B>>
where
Self: 'a;
/// Stuff wrapped result into another functor.
fn stuff<'a, A: 'a, U: 'a + Functor>(fa: Self::F<'a, U::F<'a, A>>) -> U::F<'a, Self::F<'a, A>>
where
Self: 'a;
}

View File

@ -1,9 +1,9 @@
use crate::func::*;
struct CompositionClass<U, V>(U, V);
pub struct CompositionClass<U, V>(U, V);
impl<U: WeakFunctor, V: WeakFunctor> WeakFunctor for CompositionClass<U, V> {
type F<'a, A: 'a> = U::F<'a, V::F<'a, A>> where U: 'a, V: 'a;
type F<'a, A: 'a> = U::F<'a, V::F<'a, A>> where Self: 'a;
}
impl<U: Functor, V: Functor> Functor for CompositionClass<U, V> {
@ -29,6 +29,15 @@ impl<U: Functor, V: Functor> Functor for CompositionClass<U, V> {
}
}
impl<U: Pure, V: Pure> Pure for CompositionClass<U, V> {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A>
where
Self: 'a,
{
U::pure(V::pure(a))
}
}
impl<U: ApplicativeLA2, V: ApplicativeSeq> ApplicativeSeq for CompositionClass<U, V> {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -53,3 +62,61 @@ impl<U: ApplicativeLA2, V: ApplicativeLA2> ApplicativeLA2 for CompositionClass<U
U::la2(|ua, ub| V::la2(f, ua, ub), fa, fb)
}
}
impl<U: ApplicativeTuple, V: ApplicativeTuple> ApplicativeTuple for CompositionClass<U, V> {
fn tuple<'a, A: 'a, B: 'a>(fab: (Self::F<'a, A>, Self::F<'a, B>)) -> Self::F<'a, (A, B)>
where
Self: 'a,
{
U::fmap(V::tuple, U::tuple(fab))
}
}
impl<U: Applicative, V: Applicative> Applicative for CompositionClass<U, V> {
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,
{
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,
{
U::la2(|ua, ub| V::discard_second(ua, ub), fa, fb)
}
}
impl<U: Monad, V: Monad + LocalFunctor> Monad for CompositionClass<U, V> {
fn bind<'a, A: 'a, B: 'a>(
fa: Self::F<'a, A>,
f: impl 'a + FnOnce(A) -> Self::F<'a, B>,
) -> Self::F<'a, B>
where
Self: 'a,
{
U::bind(fa, |ua| U::fmap(V::join, V::stuff::<_, U>(V::fmap(f, ua))))
}
fn ibind<'a, A: 'a, B: 'a>(
a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>,
) -> Self::F<'a, B>
where
Self: 'a,
{
U::ibind(a, move |a| {
let fx = f(a);
U::fmap(|ustate| V::unstuff(ustate), fx)
})
}
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
where
Self::F<'a, A>: 'a,
Self: 'a,
{
U::join(U::fmap(|ufa| U::fmap(V::join, V::stuff::<_, U>(ufa)), ffa))
}
}

View File

@ -28,6 +28,12 @@ impl Functor for FutureClass {
}
}
impl Pure for FutureClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Box::pin(async { a })
}
}
impl ApplicativeSeq for FutureClass {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -63,10 +69,6 @@ impl ApplicativeTuple for FutureClass {
}
impl Applicative for FutureClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Box::pin(async { a })
}
fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> {
Box::pin(async { join!(fa, fb).1 })
}

View File

@ -31,6 +31,12 @@ impl Functor for LazyClass {
}
}
impl Pure for LazyClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Box::new(|| a)
}
}
impl ApplicativeSeq for LazyClass {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -60,10 +66,6 @@ impl ApplicativeTuple for LazyClass {
}
impl Applicative for LazyClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Box::new(|| a)
}
fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> {
drop(fa);
fb

View File

@ -25,6 +25,12 @@ impl Functor for OptionClass {
}
}
impl Pure for OptionClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Some(a)
}
}
impl ApplicativeSeq for OptionClass {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -54,10 +60,6 @@ impl ApplicativeTuple for OptionClass {
}
impl Applicative for OptionClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Some(a)
}
fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> {
fa?;
fb

View File

@ -25,6 +25,12 @@ impl<E> Functor for ResultClass<E> {
}
}
impl<E> Pure for ResultClass<E> {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Ok(a)
}
}
impl<E> ApplicativeSeq for ResultClass<E> {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -54,10 +60,6 @@ impl<E> ApplicativeTuple for ResultClass<E> {
}
impl<E> Applicative for ResultClass<E> {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Ok(a)
}
fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> {
fa?;
fb

View File

@ -25,6 +25,12 @@ impl Functor for SoloClass {
}
}
impl Pure for SoloClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
a
}
}
impl ApplicativeSeq for SoloClass {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -54,10 +60,6 @@ impl ApplicativeTuple for SoloClass {
}
impl Applicative for SoloClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
a
}
fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> {
drop(fa);
fb

View File

@ -147,6 +147,12 @@ impl Functor for StacklessClass {
}
}
impl Pure for StacklessClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Stackless::from(a)
}
}
impl ApplicativeSeq for StacklessClass {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -182,10 +188,6 @@ impl ApplicativeTuple for StacklessClass {
}
impl Applicative for StacklessClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
Stackless::from(a)
}
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,

View File

@ -96,6 +96,12 @@ impl Functor for TracedClass {
}
}
impl Pure for TracedClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
a.with_trace(TraceBox::pure())
}
}
impl ApplicativeSeq for TracedClass {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -131,10 +137,6 @@ impl ApplicativeTuple for TracedClass {
}
impl Applicative for TracedClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
a.with_trace(TraceBox::pure())
}
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,

View File

@ -76,6 +76,12 @@ impl Functor for CountedClass {
}
}
impl Pure for CountedClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
a.with_count(0)
}
}
impl ApplicativeSeq for CountedClass {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
@ -111,10 +117,6 @@ impl ApplicativeTuple for CountedClass {
}
impl Applicative for CountedClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
a.with_count(0)
}
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,