use crate::{Applicative, Foldable, Functor, HKT, Monad, NoConstraint, Pure, Satisfies};
use alloc::collections::LinkedList;
pub struct LinkedListWitness;
impl HKT for LinkedListWitness {
type Constraint = NoConstraint;
type Type<T> = LinkedList<T>;
}
impl Functor<LinkedListWitness> for LinkedListWitness {
fn fmap<A, B, Func>(m_a: LinkedList<A>, f: Func) -> LinkedList<B>
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>,
Func: FnMut(A) -> B,
{
m_a.into_iter().map(f).collect()
}
}
impl Foldable<LinkedListWitness> for LinkedListWitness {
fn fold<A, B, Func>(fa: LinkedList<A>, init: B, f: Func) -> B
where
Func: FnMut(B, A) -> B,
{
fa.into_iter().fold(init, f)
}
}
impl Pure<LinkedListWitness> for LinkedListWitness {
fn pure<T>(value: T) -> LinkedList<T>
where
T: Satisfies<NoConstraint>,
{
let mut list = LinkedList::new();
list.push_back(value);
list
}
}
impl Applicative<LinkedListWitness> for LinkedListWitness {
fn apply<A, B, Func>(f_ab: LinkedList<Func>, f_a: LinkedList<A>) -> LinkedList<B>
where
A: Satisfies<NoConstraint> + Clone,
B: Satisfies<NoConstraint>,
Func: Satisfies<NoConstraint> + FnMut(A) -> B,
{
f_ab.into_iter()
.flat_map(|mut f_val| {
f_a.iter()
.map(move |a_val| f_val(a_val.clone()))
.collect::<LinkedList<B>>()
})
.collect()
}
}
impl Monad<LinkedListWitness> for LinkedListWitness {
fn bind<A, B, Func>(m_a: LinkedList<A>, f: Func) -> LinkedList<B>
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>,
Func: FnMut(A) -> LinkedList<B>,
{
m_a.into_iter().flat_map(f).collect()
}
}