Pure + LocalFunctor
This commit is contained in:
parent
e89e44d129
commit
1a5e9f15f3
28
src/func.rs
28
src/func.rs
@ -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;
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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 })
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user