EffectClass
This commit is contained in:
parent
9f9ff0bf76
commit
caca9add1b
@ -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
185
src/func/classes/effect.rs
Normal 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,
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user