use alloc::vec::Vec;
use crate::CausalTensor;
use deep_causality_haft::{
Convolutional, Foldable, Functor, HKT, MonoidalApplicative, Semigroupal,
};
pub struct ZipTensorWitness;
impl HKT for ZipTensorWitness {
type Type<T> = CausalTensor<T>;
}
impl Functor<ZipTensorWitness> for ZipTensorWitness {
fn fmap<A, B, Func>(m_a: CausalTensor<A>, f: Func) -> CausalTensor<B>
where
Func: FnMut(A) -> B,
{
let shape = m_a.shape().to_vec();
let new_data: Vec<B> = m_a.into_vec().into_iter().map(f).collect();
CausalTensor::from_vec(new_data, &shape)
}
}
impl Semigroupal<ZipTensorWitness> for ZipTensorWitness {
fn zip_with<A, B, C, Func>(
fa: CausalTensor<A>,
fb: CausalTensor<B>,
mut f: Func,
) -> CausalTensor<C>
where
Func: FnMut(A, B) -> C,
{
let same_shape = fa.shape() == fb.shape();
let shape = fa.shape().to_vec();
let data: Vec<C> = fa
.into_vec()
.into_iter()
.zip(fb.into_vec())
.map(|(a, b)| f(a, b))
.collect();
if same_shape {
CausalTensor::from_vec(data, &shape)
} else {
let len = data.len();
CausalTensor::from_vec(data, &[len])
}
}
}
impl Foldable<ZipTensorWitness> for ZipTensorWitness {
fn fold<A, B, Func>(fa: CausalTensor<A>, init: B, f: Func) -> B
where
Func: FnMut(B, A) -> B,
{
fa.into_vec().into_iter().fold(init, f)
}
}
impl Convolutional<ZipTensorWitness> for ZipTensorWitness {}
impl MonoidalApplicative<ZipTensorWitness> for ZipTensorWitness {}