use core::marker::PhantomData;
use comp_cat_rs::foundation::{Braided, Category, Iso, MonoidalCategory, Symmetric};
use crate::category::arrow::CircuitArrow;
use crate::shape::Shape;
#[derive(Debug, Clone, Copy)]
pub struct CircuitCat;
#[derive(Debug, Clone, Copy)]
pub struct TensorObj<A, B> {
_phantom: PhantomData<(A, B)>,
}
#[derive(Debug, Clone, Copy)]
pub struct UnitShape;
impl From<Shape> for CircuitCat {
fn from(_: Shape) -> Self {
Self
}
}
impl From<UnitShape> for CircuitCat {
fn from(_: UnitShape) -> Self {
Self
}
}
impl<A, B> From<TensorObj<A, B>> for CircuitCat {
fn from(_: TensorObj<A, B>) -> Self {
Self
}
}
impl Category for CircuitCat {
type Hom<A: Into<Self>, B: Into<Self>> = CircuitArrow;
fn id<A: Into<Self> + Clone>(_a: &A) -> Self::Hom<A, A> {
CircuitArrow::IdAbstract
}
fn comp<A, B, C>(f: Self::Hom<A, B>, g: Self::Hom<B, C>) -> Self::Hom<A, C>
where
A: Into<Self>,
B: Into<Self>,
C: Into<Self>,
{
CircuitArrow::compose_unchecked(f, g)
}
}
impl MonoidalCategory for CircuitCat {
type Tensor<A: Into<Self>, B: Into<Self>> = TensorObj<A, B>;
type Unit = UnitShape;
fn tensor_map<A, B, C, D>(
f: Self::Hom<A, B>,
g: Self::Hom<C, D>,
) -> Self::Hom<Self::Tensor<A, C>, Self::Tensor<B, D>>
where
A: Into<Self>,
B: Into<Self>,
C: Into<Self>,
D: Into<Self>,
{
CircuitArrow::tensor(f, g)
}
fn associator<A, B, C>() -> Iso<
Self,
Self::Tensor<Self::Tensor<A, B>, C>,
Self::Tensor<A, Self::Tensor<B, C>>,
>
where
A: Into<Self>,
B: Into<Self>,
C: Into<Self>,
{
Iso::new(CircuitArrow::IdAbstract, CircuitArrow::IdAbstract)
}
fn left_unitor<A>() -> Iso<Self, Self::Tensor<Self::Unit, A>, A>
where
A: Into<Self>,
{
Iso::new(CircuitArrow::IdAbstract, CircuitArrow::IdAbstract)
}
fn right_unitor<A>() -> Iso<Self, Self::Tensor<A, Self::Unit>, A>
where
A: Into<Self>,
{
Iso::new(CircuitArrow::IdAbstract, CircuitArrow::IdAbstract)
}
}
impl Braided for CircuitCat {
fn braid<A, B>() -> Iso<Self, Self::Tensor<A, B>, Self::Tensor<B, A>>
where
A: Into<Self>,
B: Into<Self>,
{
Iso::new(CircuitArrow::IdAbstract, CircuitArrow::IdAbstract)
}
}
impl Symmetric for CircuitCat {}
#[cfg(test)]
mod tests {
use super::{CircuitCat, CircuitArrow, Shape};
use comp_cat_rs::foundation::{Category, MonoidalCategory};
#[test]
fn category_comp_builds_nested_arrow() {
let f: CircuitArrow = CircuitArrow::passthrough(Shape::new(2, 8));
let g: CircuitArrow = CircuitArrow::passthrough(Shape::new(2, 8));
let h = <CircuitCat as Category>::comp::<Shape, Shape, Shape>(f, g);
match h {
CircuitArrow::Compose { .. } => {}
CircuitArrow::Id(_)
| CircuitArrow::IdAbstract
| CircuitArrow::FullAdder
| CircuitArrow::Csa3to2 { .. }
| CircuitArrow::Braid { .. }
| CircuitArrow::Passthrough(_)
| CircuitArrow::Tensor { .. } => panic!("expected Compose"),
}
}
#[test]
fn monoidal_tensor_map_builds_tensor() {
let f = CircuitArrow::passthrough(Shape::new(1, 4));
let g = CircuitArrow::passthrough(Shape::new(1, 4));
let t = <CircuitCat as MonoidalCategory>::tensor_map::<Shape, Shape, Shape, Shape>(f, g);
match t {
CircuitArrow::Tensor { .. } => {}
CircuitArrow::Id(_)
| CircuitArrow::IdAbstract
| CircuitArrow::FullAdder
| CircuitArrow::Csa3to2 { .. }
| CircuitArrow::Braid { .. }
| CircuitArrow::Passthrough(_)
| CircuitArrow::Compose { .. } => panic!("expected Tensor"),
}
}
#[test]
fn id_returns_abstract() {
let s = Shape::new(3, 8);
let a = <CircuitCat as Category>::id::<Shape>(&s);
match a {
CircuitArrow::IdAbstract => {}
CircuitArrow::Id(_)
| CircuitArrow::FullAdder
| CircuitArrow::Csa3to2 { .. }
| CircuitArrow::Braid { .. }
| CircuitArrow::Passthrough(_)
| CircuitArrow::Tensor { .. }
| CircuitArrow::Compose { .. } => panic!("expected IdAbstract"),
}
}
}