use crate::{
Applicative, Foldable, Functor, HKT, HKT2, Monad, NoConstraint, Placeholder, Pure, Satisfies,
Traversable,
};
pub struct ResultWitness<E>(Placeholder, E);
impl<E> HKT2<E> for ResultWitness<E> {
type Type<T> = Result<T, E>;
}
impl<E> HKT for ResultWitness<E> {
type Constraint = NoConstraint;
type Type<T> = Result<T, E>;
}
impl<E> Functor<ResultWitness<E>> for ResultWitness<E>
where
E: 'static,
{
fn fmap<A, B, Func>(
m_a: <ResultWitness<E> as HKT2<E>>::Type<A>,
f: Func,
) -> <ResultWitness<E> as HKT2<E>>::Type<B>
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>,
Func: FnMut(A) -> B,
{
m_a.map(f)
}
}
impl<E> Pure<ResultWitness<E>> for ResultWitness<E>
where
E: 'static + Clone,
{
fn pure<T>(value: T) -> <ResultWitness<E> as HKT2<E>>::Type<T>
where
T: Satisfies<NoConstraint>,
{
Ok(value)
}
}
impl<E> Applicative<ResultWitness<E>> for ResultWitness<E>
where
E: 'static + Clone,
{
fn apply<A, B, Func>(
f_ab: <ResultWitness<E> as HKT2<E>>::Type<Func>,
f_a: <ResultWitness<E> as HKT2<E>>::Type<A>,
) -> <ResultWitness<E> as HKT2<E>>::Type<B>
where
A: Satisfies<NoConstraint> + Clone,
B: Satisfies<NoConstraint>,
Func: Satisfies<NoConstraint> + FnMut(A) -> B,
{
match f_ab {
Ok(mut f) => match f_a {
Ok(a) => Ok(f(a)),
Err(e) => Err(e),
},
Err(e) => Err(e),
}
}
}
impl<E> Foldable<ResultWitness<E>> for ResultWitness<E>
where
E: 'static,
{
fn fold<A, B, Func>(fa: Result<A, E>, init: B, mut f: Func) -> B
where
Func: FnMut(B, A) -> B,
{
match fa {
Ok(a) => f(init, a),
Err(_) => init,
}
}
}
impl<E> Monad<ResultWitness<E>> for ResultWitness<E>
where
E: 'static + Clone,
{
fn bind<A, B, Func>(
m_a: <ResultWitness<E> as HKT2<E>>::Type<A>,
mut f: Func,
) -> <ResultWitness<E> as HKT2<E>>::Type<B>
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>,
Func: FnMut(A) -> <ResultWitness<E> as HKT2<E>>::Type<B>,
{
match m_a {
Ok(a) => f(a),
Err(e) => Err(e),
}
}
}
impl<E> Traversable<ResultWitness<E>> for ResultWitness<E>
where
E: 'static + Clone, {
fn sequence<A, M>(
fa: <ResultWitness<E> as HKT2<E>>::Type<M::Type<A>>,
) -> <M as HKT>::Type<<ResultWitness<E> as HKT2<E>>::Type<A>>
where
M: Applicative<M> + HKT,
A: Clone + Satisfies<NoConstraint> + Satisfies<M::Constraint>,
M::Type<A>: Satisfies<NoConstraint>,
Result<A, E>: Satisfies<M::Constraint>,
{
match fa {
Ok(m_a) => M::fmap(m_a, |a_val: A| Ok(a_val)),
Err(e) => M::pure(Err(e.clone())),
}
}
}
use crate::{Bifunctor, HKT2Unbound};
pub struct ResultUnboundWitness;
impl HKT2Unbound for ResultUnboundWitness {
type Constraint = NoConstraint;
type Type<A, B> = Result<A, B>;
}
impl Bifunctor<ResultUnboundWitness> for ResultUnboundWitness {
fn bimap<A, B, C, D, F1, F2>(fab: Result<A, B>, mut f1: F1, mut f2: F2) -> Result<C, D>
where
F1: FnMut(A) -> C,
F2: FnMut(B) -> D,
{
match fab {
Ok(a) => Ok(f1(a)),
Err(b) => Err(f2(b)),
}
}
}