{-# OPTIONS --without-K --safe #-}
module Categories.Tactic.Monoidal.Free where
open import Level using (Level)
open import Data.List.Base using (List; []; _∷_; _++_)
open import Data.List.Properties using (++-assoc; ++-identityʳ)
open import Relation.Binary.PropositionalEquality
using (_≡_; refl; sym; trans; cong; cong₂)
module Free {a : Level} (Atom : Set a) where
infixr 9 _⊗_
data Ob : Set a where
‹_› : Atom → Ob
I : Ob
_⊗_ : Ob → Ob → Ob
infixr 9 _∘_
infixr 10 _⊗₁_
data _⇒_ : Ob → Ob → Set a where
idₘ : ∀ {X} → X ⇒ X
_∘_ : ∀ {X Y Z} → Y ⇒ Z → X ⇒ Y → X ⇒ Z
_⊗₁_ : ∀ {X Y Z W} → X ⇒ Y → Z ⇒ W → (X ⊗ Z) ⇒ (Y ⊗ W)
α⇒ : ∀ {X Y Z} → ((X ⊗ Y) ⊗ Z) ⇒ (X ⊗ (Y ⊗ Z))
α⇐ : ∀ {X Y Z} → (X ⊗ (Y ⊗ Z)) ⇒ ((X ⊗ Y) ⊗ Z)
λ⇒ : ∀ {X} → (I ⊗ X) ⇒ X
λ⇐ : ∀ {X} → X ⇒ (I ⊗ X)
ρ⇒ : ∀ {X} → (X ⊗ I) ⇒ X
ρ⇐ : ∀ {X} → X ⇒ (X ⊗ I)
invert : ∀ {X Y} → X ⇒ Y → Y ⇒ X
invert idₘ = idₘ
invert (g ∘ f) = invert f ∘ invert g
invert (f ⊗₁ g) = invert f ⊗₁ invert g
invert α⇒ = α⇐
invert α⇐ = α⇒
invert λ⇒ = λ⇐
invert λ⇐ = λ⇒
invert ρ⇒ = ρ⇐
invert ρ⇐ = ρ⇒
nf : Ob → List Atom
nf ‹ x › = x ∷ []
nf I = []
nf (X ⊗ Y) = nf X ++ nf Y
⌜_⌝ : List Atom → Ob
⌜ [] ⌝ = I
⌜ x ∷ xs ⌝ = ‹ x › ⊗ ⌜ xs ⌝
nf-⌜⌝ : (w : List Atom) → nf ⌜ w ⌝ ≡ w
nf-⌜⌝ [] = refl
nf-⌜⌝ (x ∷ xs) = cong (x ∷_) (nf-⌜⌝ xs)
module NormalForm where
assocₙ : (X Y Z : Ob) → nf ((X ⊗ Y) ⊗ Z) ≡ nf (X ⊗ (Y ⊗ Z))
assocₙ X Y Z = ++-assoc (nf X) (nf Y) (nf Z)
assocₙ⁻¹ : (X Y Z : Ob) → nf (X ⊗ (Y ⊗ Z)) ≡ nf ((X ⊗ Y) ⊗ Z)
assocₙ⁻¹ X Y Z = sym (assocₙ X Y Z)
unitʳₙ : (X : Ob) → nf (X ⊗ I) ≡ nf X
unitʳₙ X = ++-identityʳ (nf X)
unitʳₙ⁻¹ : (X : Ob) → nf X ≡ nf (X ⊗ I)
unitʳₙ⁻¹ X = sym (unitʳₙ X)
⇒⇒nf : ∀ {X Y} → X ⇒ Y → nf X ≡ nf Y
⇒⇒nf idₘ = refl
⇒⇒nf (g ∘ f) = trans (⇒⇒nf f) (⇒⇒nf g)
⇒⇒nf (f ⊗₁ g) = cong₂ _++_ (⇒⇒nf f) (⇒⇒nf g)
⇒⇒nf (α⇒ {X} {Y} {Z}) = NormalForm.assocₙ X Y Z
⇒⇒nf (α⇐ {X} {Y} {Z}) = NormalForm.assocₙ⁻¹ X Y Z
⇒⇒nf λ⇒ = refl
⇒⇒nf λ⇐ = refl
⇒⇒nf (ρ⇒ {X}) = NormalForm.unitʳₙ X
⇒⇒nf (ρ⇐ {X}) = NormalForm.unitʳₙ⁻¹ X