EffectClass
This commit is contained in:
parent
9f9ff0bf76
commit
caca9add1b
@ -20,6 +20,7 @@
|
|||||||
use crate::func::*;
|
use crate::func::*;
|
||||||
|
|
||||||
pub mod composition;
|
pub mod composition;
|
||||||
|
pub mod effect;
|
||||||
pub mod future;
|
pub mod future;
|
||||||
pub mod lazy;
|
pub mod lazy;
|
||||||
pub mod option;
|
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