use crate::CausalMultiVector;
use deep_causality_haft::{
Adjunction, Applicative, CoMonad, Foldable, Functor, HKT, Monad, NoConstraint, Pure, Satisfies,
};
use deep_causality_metric::Metric;
pub struct CausalMultiVectorWitness;
impl HKT for CausalMultiVectorWitness {
type Constraint = NoConstraint;
type Type<T> = CausalMultiVector<T>;
}
impl Functor<CausalMultiVectorWitness> for CausalMultiVectorWitness {
fn fmap<A, B, Func>(fa: CausalMultiVector<A>, f: Func) -> CausalMultiVector<B>
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>,
Func: FnMut(A) -> B,
{
let metric = fa.metric;
let data = fa.data.into_iter().map(f).collect();
CausalMultiVector { data, metric }
}
}
impl Pure<CausalMultiVectorWitness> for CausalMultiVectorWitness {
fn pure<T>(value: T) -> CausalMultiVector<T>
where
T: Satisfies<NoConstraint>,
{
let metric = Metric::Euclidean(0);
let data = vec![value];
CausalMultiVector { data, metric }
}
}
impl Applicative<CausalMultiVectorWitness> for CausalMultiVectorWitness {
fn apply<A, B, Func>(
f_ab: CausalMultiVector<Func>,
f_a: CausalMultiVector<A>,
) -> CausalMultiVector<B>
where
A: Satisfies<NoConstraint> + Clone,
B: Satisfies<NoConstraint>,
Func: Satisfies<NoConstraint> + FnMut(A) -> B,
{
let metric = f_a.metric;
let funcs = f_ab.data;
let args = f_a.data;
let data = if funcs.len() == 1 {
let f = funcs.into_iter().next().unwrap();
args.into_iter().map(f).collect()
} else if funcs.len() == args.len() {
funcs.into_iter().zip(args).map(|(mut f, a)| f(a)).collect()
} else {
panic!(
"Applicative::apply shape mismatch: {} funcs vs {} args",
funcs.len(),
args.len()
);
};
CausalMultiVector { data, metric }
}
}
impl Foldable<CausalMultiVectorWitness> for CausalMultiVectorWitness {
fn fold<A, B, Func>(fa: CausalMultiVector<A>, init: B, f: Func) -> B
where
A: Satisfies<NoConstraint>,
Func: FnMut(B, A) -> B,
{
fa.data.into_iter().fold(init, f)
}
}
impl Monad<CausalMultiVectorWitness> for CausalMultiVectorWitness {
fn bind<A, B, Func>(ma: CausalMultiVector<A>, mut f: Func) -> CausalMultiVector<B>
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>,
Func: FnMut(A) -> CausalMultiVector<B>,
{
let mut results = Vec::new();
let mut out_metric = ma.metric;
for a in ma.data {
let mb = f(a);
out_metric = mb.metric;
results.extend(mb.data);
}
CausalMultiVector {
data: results,
metric: out_metric,
}
}
}
impl CoMonad<CausalMultiVectorWitness> for CausalMultiVectorWitness {
fn extract<A>(fa: &CausalMultiVector<A>) -> A
where
A: Satisfies<NoConstraint> + Clone,
{
fa.data.first().cloned().expect("Empty MultiVector")
}
fn extend<A, B, Func>(fa: &CausalMultiVector<A>, mut f: Func) -> CausalMultiVector<B>
where
Func: FnMut(&CausalMultiVector<A>) -> B,
A: Satisfies<NoConstraint> + Clone,
B: Satisfies<NoConstraint>,
{
let n = fa.data.len();
let mut result_data = Vec::with_capacity(n);
for i in 0..n {
let mut rotated_data = Vec::with_capacity(n);
for k in 0..n {
let idx = (i + k) % n;
rotated_data.push(fa.data[idx].clone());
}
let view = CausalMultiVector {
data: rotated_data,
metric: fa.metric,
};
result_data.push(f(&view));
}
CausalMultiVector {
data: result_data,
metric: fa.metric,
}
}
}
impl Adjunction<CausalMultiVectorWitness, CausalMultiVectorWitness, Metric>
for CausalMultiVectorWitness
{
fn unit<A>(ctx: &Metric, a: A) -> CausalMultiVector<CausalMultiVector<A>>
where
A: Satisfies<NoConstraint> + Satisfies<NoConstraint> + Clone,
{
let inner_data = vec![a];
let inner_mv = CausalMultiVector {
data: inner_data,
metric: *ctx,
};
let outer_data = vec![inner_mv];
CausalMultiVector {
data: outer_data,
metric: Metric::Euclidean(0),
}
}
fn counit<B>(_ctx: &Metric, lrb: CausalMultiVector<CausalMultiVector<B>>) -> B
where
B: Satisfies<NoConstraint> + Satisfies<NoConstraint> + Clone,
{
let flattened =
<CausalMultiVectorWitness as Monad<CausalMultiVectorWitness>>::bind(lrb, |x| x);
<CausalMultiVectorWitness as CoMonad<CausalMultiVectorWitness>>::extract(&flattened)
}
fn left_adjunct<A, B, F>(ctx: &Metric, a: A, f: F) -> CausalMultiVector<B>
where
A: Satisfies<NoConstraint> + Satisfies<NoConstraint> + Clone,
B: Satisfies<NoConstraint>,
F: Fn(CausalMultiVector<A>) -> B,
{
let unit_res = Self::unit(ctx, a);
Self::fmap(unit_res, f)
}
fn right_adjunct<A, B, F>(_ctx: &Metric, la: CausalMultiVector<A>, f: F) -> B
where
A: Satisfies<NoConstraint> + Clone,
B: Satisfies<NoConstraint> + Satisfies<NoConstraint>,
F: FnMut(A) -> CausalMultiVector<B>,
{
let mapped = Self::fmap(la, f);
let mut outer_iter = mapped.data.into_iter();
if let Some(inner_mv) = outer_iter.next() {
let mut inner_iter = inner_mv.data.into_iter();
if let Some(b) = inner_iter.next() {
return b;
}
}
panic!("Adjunction::right_adjunct resulted in empty MultiVector");
}
}