use super::*;
use super::types::*;
pub trait Functor {
fn fmap<A, B, F: Fn(A) -> B>(f: F, a: K1<Self, A>) -> K1<Self, B>;
}
impl Functor for OptionC {
fn fmap<A, B, F: Fn(A) -> B>(f: F, a: K1<Self, A>) -> K1<Self, B> {
K1::new(a.into_inner().map(f))
}
}
impl Functor for VecC {
fn fmap<A, B, F: Fn(A) -> B>(f: F, a: K1<Self, A>) -> K1<Self, B> {
K1::new(a.into_inner().into_iter().map(f).collect())
}
}
impl<T> Functor for ResultLeft<T> {
fn fmap<A, B, F: Fn(A) -> B>(f: F, a: K1<Self, A>) -> K1<Self, B> {
Self::new(a.into_inner().map_err(f))
}
}
impl<E> Functor for ResultRight<E> {
fn fmap<A, B, F: Fn(A) -> B>(f: F, a: K1<Self, A>) -> K1<Self, B> {
Self::new(a.into_inner().map(f))
}
}
impl<T> Functor for PairLeft<T> {
fn fmap<A, B, F: Fn(A) -> B>(f: F, a: K1<Self, A>) -> K1<Self, B> {
let a = a.into_inner();
Self::new((a.0, f(a.1)))
}
}
impl<T> Functor for PairRight<T> {
fn fmap<A, B, F: Fn(A) -> B>(f: F, a: K1<Self, A>) -> K1<Self, B> {
let a = a.into_inner();
Self::new((f(a.0), a.1))
}
}
#[cfg(test)]
mod test {
use super::*;
fn check_law_id<T, F: Functor + Kind1<T>>(input: K1<F, T>)
where
K1Type<F, T>: PartialEq + core::fmt::Debug + Clone,
{
let output = F::fmap(|x| x, input.clone());
assert_eq!(input, output);
}
fn check_law_compose<T, F: Functor + Kind1<T>, G, H>(g: G, h: H, input: K1<F, T>)
where
G: Fn(T) -> T,
H: Fn(T) -> T,
K1Type<F, T>: PartialEq + core::fmt::Debug + Clone,
{
let composed_first = F::fmap(|x| g(h(x)), input.clone());
let fmapped_first = F::fmap(g, F::fmap(h, input));
assert_eq!(composed_first, fmapped_first);
}
#[test]
fn option_functor_law_id() {
let nothing: Option<i32> = None;
check_law_id(OptionC::new(nothing));
let something: Option<i32> = Some(42);
check_law_id(OptionC::new(something));
}
#[test]
fn option_functor_law_compose() {
let g = |x| x + 1;
let h = |x| x * 2;
check_law_compose::<i32, _, _, _>(&g, &h, OptionC::new(None));
check_law_compose(&g, &h, OptionC::new(Some(42)));
}
#[test]
fn vec_functor_law_id() {
let nothing: Vec<i32> = vec![];
check_law_id(VecC::new(nothing));
let something: Vec<i32> = vec![1, 2, 3];
check_law_id(VecC::new(something));
}
#[test]
fn vec_functor_law_compose() {
let g = |x| x + 1;
let h = |x| x * 2;
check_law_compose::<i32, _, _, _>(&g, &h, VecC::new(vec![]));
check_law_compose(&g, &h, VecC::new(vec![1, 2, 3]));
}
#[test]
fn result_left_functor_law_id() {
let great: Result<i32, String> = Ok(42);
check_law_id(ResultLeft::new(great));
let not_great: Result<String, i32> = Err(42);
check_law_id(ResultLeft::new(not_great));
}
#[test]
fn result_left_functor_law_compose() {
let g = |x| x + 1;
let h = |x| x * 2;
check_law_compose::<i32, _, _, _>(&g, &h, ResultLeft::<i32>::new(Err(42)));
check_law_compose(&g, &h, ResultLeft::new(Ok(42)));
}
#[test]
fn result_right_functor_law_id() {
let great: Result<i32, String> = Ok(42);
check_law_id(ResultRight::new(great));
let not_great: Result<String, i32> = Err(42);
check_law_id(ResultRight::new(not_great));
}
#[test]
fn result_right_functor_law_compose() {
let g = |x| x + 1;
let h = |x| x * 2;
check_law_compose::<i32, _, _, _>(&g, &h, ResultRight::new(Err(42)));
check_law_compose(&g, &h, ResultRight::<i32>::new(Ok(42)));
}
#[test]
fn pair_left_functor_law_id() {
check_law_id(PairLeft::new(("foobar", 42)));
}
#[test]
fn pair_left_functor_law_compose() {
let g = |x| x + 1;
let h = |x| x * 2;
check_law_compose(&g, &h, PairLeft::new(("foobar", 42)));
}
#[test]
fn pair_right_functor_law_id() {
check_law_id(PairRight::new((42, "foobar")));
}
#[test]
fn pair_right_functor_law_compose() {
let g = |x| x + 1;
let h = |x| x * 2;
check_law_compose(&g, &h, PairRight::new((42, "foobar")));
}
}