use crate::{Chain, SimplicialComplex};
use deep_causality_haft::{
Adjunction, CoMonad, Foldable, Functor, HKT, NoConstraint, Pure, Satisfies,
};
use deep_causality_sparse::CsrMatrixWitness;
use std::sync::Arc;
pub struct ChainWitness;
impl HKT for ChainWitness {
type Constraint = NoConstraint;
type Type<T>
= Chain<T>
where
T: Satisfies<NoConstraint>;
}
impl Functor<ChainWitness> for ChainWitness {
fn fmap<A, B, Func>(fa: Chain<A>, f: Func) -> Chain<B>
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>, Func: FnMut(A) -> B,
{
let new_weights = <CsrMatrixWitness as Functor<CsrMatrixWitness>>::fmap(fa.weights, f);
let new_complex = SimplicialComplex::<B> {
skeletons: fa.complex.skeletons.clone(),
boundary_operators: fa.complex.boundary_operators.clone(),
coboundary_operators: fa.complex.coboundary_operators.clone(),
..Default::default()
};
Chain::new(Arc::new(new_complex), fa.grade, new_weights)
}
}
impl Foldable<ChainWitness> for ChainWitness {
fn fold<A, B, Func>(fa: Chain<A>, init: B, f: Func) -> B
where
A: Satisfies<NoConstraint>,
Func: FnMut(B, A) -> B,
{
<CsrMatrixWitness as Foldable<CsrMatrixWitness>>::fold(fa.weights, init, f)
}
}
impl<T> Adjunction<ChainWitness, ChainWitness, (Arc<SimplicialComplex<T>>, usize)> for ChainWitness
where
T: Satisfies<NoConstraint>,
{
fn unit<A>(ctx: &(Arc<SimplicialComplex<T>>, usize), a: A) -> Chain<Chain<A>>
where
A: Satisfies<NoConstraint> + Satisfies<NoConstraint> + Clone,
{
let (complex, grade) = ctx;
let complex_a = SimplicialComplex::<A> {
skeletons: complex.skeletons.clone(),
boundary_operators: complex.boundary_operators.clone(),
coboundary_operators: complex.coboundary_operators.clone(),
..Default::default()
};
let arc_complex_a = Arc::new(complex_a);
let inner_weights = <CsrMatrixWitness as Pure<CsrMatrixWitness>>::pure(a);
let inner_chain = Chain::new(arc_complex_a.clone(), *grade, inner_weights);
let complex_chain_a = SimplicialComplex::<Chain<A>> {
skeletons: complex.skeletons.clone(),
boundary_operators: complex.boundary_operators.clone(),
coboundary_operators: complex.coboundary_operators.clone(),
..Default::default()
};
let outer_weights = <CsrMatrixWitness as Pure<CsrMatrixWitness>>::pure(inner_chain);
Chain::new(Arc::new(complex_chain_a), *grade, outer_weights)
}
fn counit<B>(_ctx: &(Arc<SimplicialComplex<T>>, usize), lrb: Chain<Chain<B>>) -> B
where
B: Satisfies<NoConstraint> + Satisfies<NoConstraint> + Clone,
{
let inner_chain = <CsrMatrixWitness as CoMonad<CsrMatrixWitness>>::extract(&lrb.weights);
<CsrMatrixWitness as CoMonad<CsrMatrixWitness>>::extract(&inner_chain.weights)
}
fn left_adjunct<A, B, F>(ctx: &(Arc<SimplicialComplex<T>>, usize), a: A, f: F) -> Chain<B>
where
A: Satisfies<NoConstraint> + Satisfies<NoConstraint> + Clone,
B: Satisfies<NoConstraint>,
F: FnMut(Chain<A>) -> B,
{
let wrapped = Self::unit(ctx, a);
Self::fmap(wrapped, f)
}
fn right_adjunct<A, B, F>(_ctx: &(Arc<SimplicialComplex<T>>, usize), la: Chain<A>, f: F) -> B
where
A: Satisfies<NoConstraint> + Clone,
B: Satisfies<NoConstraint> + Satisfies<NoConstraint> + Clone, F: FnMut(A) -> Chain<B>,
{
let result_chain: Chain<Chain<B>> = Self::fmap(la, f);
let (_, _, outer_values, _) = result_chain.weights.into_parts();
if let Some(inner_chain) = outer_values.into_iter().next() {
let (_, _, inner_values, _) = inner_chain.weights.into_parts();
if let Some(val) = inner_values.into_iter().next() {
return val;
}
}
panic!("Adjunction::right_adjunct resulted in empty chain.");
}
}