EffectClass

This commit is contained in:
AF 2023-05-14 05:56:58 +00:00
parent 9f9ff0bf76
commit caca9add1b
2 changed files with 186 additions and 0 deletions

View File

@ -20,6 +20,7 @@
use crate::func::*;
pub mod composition;
pub mod effect;
pub mod future;
pub mod lazy;
pub mod option;

185
src/func/classes/effect.rs Normal file
View File

@ -0,0 +1,185 @@
use crate::func::*;
pub trait Effect {
fn pure() -> Self;
fn seq(lhs: Self, rhs: Self) -> Self;
fn after(self, effect: Self) -> Self;
}
#[derive(Clone)]
pub struct WithEffect<A, E> {
value: A,
effect: E,
}
impl<A, E: Effect> WithEffect<A, E> {
fn after(self, effect: E) -> Self {
WithEffect {
value: self.value,
effect: self.effect.after(effect),
}
}
}
#[derive(SharedFunctor, CovariantFunctor)]
pub struct EffectClass<E>(E);
impl<E> WeakFunctor for EffectClass<E> {
type F<'a, A: 'a> = WithEffect<A, E>
where
Self: 'a;
}
impl<E> Functor for EffectClass<E> {
fn fmap<'a, A: 'a, B: 'a>(f: impl 'a + FnOnce(A) -> B, fa: Self::F<'a, A>) -> Self::F<'a, B>
where
Self: 'a,
{
WithEffect {
value: f(fa.value),
effect: fa.effect,
}
}
fn replace<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, b: B) -> Self::F<'a, B>
where
Self: 'a,
{
drop(fa.value);
WithEffect {
value: b,
effect: fa.effect,
}
}
}
impl<E: Effect> Pure for EffectClass<E> {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A>
where
Self: 'a,
{
WithEffect {
value: a,
effect: E::pure(),
}
}
}
impl<E: Effect> ApplicativeSeq for EffectClass<E> {
fn seq<'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,
{
WithEffect {
value: (ff.value)(fa.value),
effect: E::seq(ff.effect, fa.effect),
}
}
}
impl<E: Effect> ApplicativeLA2 for EffectClass<E> {
fn la2<'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,
{
WithEffect {
value: f(fa.value, fb.value),
effect: E::seq(fa.effect, fb.effect),
}
}
}
impl<E: Effect> ApplicativeTuple for EffectClass<E> {
fn tuple<'a, A: 'a, B: 'a>((fa, fb): (Self::F<'a, A>, Self::F<'a, B>)) -> Self::F<'a, (A, B)>
where
Self: 'a,
{
WithEffect {
value: (fa.value, fb.value),
effect: E::seq(fa.effect, fb.effect),
}
}
}
impl<E: Effect> Applicative for EffectClass<E> {
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,
{
drop(fa.value);
WithEffect {
value: fb.value,
effect: E::seq(fa.effect, fb.effect),
}
}
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,
{
drop(fb.value);
WithEffect {
value: fa.value,
effect: E::seq(fa.effect, fb.effect),
}
}
}
impl<E: Effect> Monad for EffectClass<E> {
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,
{
f(fa.value).after(fa.effect)
}
fn iterate<'a, B: 'a>(mut f: impl Iterative<'a, T = Self, B = B>) -> Self::F<'a, B>
where
Self: 'a,
{
let mut effect = E::pure();
loop {
let fa = f.next();
effect = fa.effect.after(effect);
match fa.value {
ControlFlow::Continue(next_f) => f = next_f,
ControlFlow::Break(b) => return WithEffect { value: b, effect },
}
}
}
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,
{
ffa.value.after(ffa.effect)
}
}
impl<E> LocalFunctor for EffectClass<E> {
fn stuff<'a, A: 'a, T: 'a + Pure>(fa: Self::F<'a, T::F<'a, A>>) -> T::F<'a, Self::F<'a, A>>
where
Self: 'a,
{
T::fmap(
|a| WithEffect {
value: a,
effect: fa.effect,
},
fa.value,
)
}
}