{-# OPTIONS --safe --cubical-compatible --exact-split --guardedness --double-check #-}
module ALMA.InitialPass.ContCategory where
open import Agda.Primitive using (Level; lsuc; _⊔_)
open import Relation.Binary.Structures using (IsEquivalence)
open import Relation.Binary.PropositionalEquality
using (_≡_; refl; sym; trans; cong; subst; module ≡-Reasoning)
open ≡-Reasoning
open import Relation.Binary.PropositionalEquality.Properties
using (subst-subst; subst-subst-sym)
open import Data.Container.Core using (Container; _⇒_; Shape; Position)
open import Data.Container.Morphism using (id; _∘_)
open import Categories.Category using (Category)
infix 4 _≈M_
record _≈M_ {s p : Level} {C D : Container s p} (f g : C ⇒ D) : Set (s ⊔ p) where
private
module f = _⇒_ f
module g = _⇒_ g
field
shape-eq : ∀ (s : Shape C) → f.shape s ≡ g.shape s
pos-eq : ∀ (s : Shape C) (p : Position D (f.shape s))
→ f.position {s} p ≡ g.position {s} (subst (Position D) (shape-eq s) p)
≈M-refl : ∀ {s p} {C D : Container s p} {f : C ⇒ D} → f ≈M f
≈M-refl = record { shape-eq = λ _ → refl ; pos-eq = λ _ _ → refl }
≈M-sym : ∀ {s p} {C D : Container s p} {f g : C ⇒ D} → f ≈M g → g ≈M f
≈M-sym {s} {p} {C} {D} {f} {g} eq = record
{ shape-eq = λ s → sym (eq.shape-eq s)
; pos-eq = λ s q → sym (begin
F.position {s} (subst (Position D) (sym (eq.shape-eq s)) q)
≡⟨ eq.pos-eq s (subst (Position D) (sym (eq.shape-eq s)) q) ⟩
G.position {s} (subst (Position D) (eq.shape-eq s) (subst (Position D) (sym (eq.shape-eq s)) q))
≡⟨ cong (G.position {s}) (subst-subst-sym (eq.shape-eq s)) ⟩
G.position {s} q
∎)
}
where
module F = _⇒_ f
module G = _⇒_ g
module eq = _≈M_ eq
≈M-trans : ∀ {s p} {C D : Container s p} {f g h : C ⇒ D} → f ≈M g → g ≈M h → f ≈M h
≈M-trans {s} {p} {C} {D} {f} {g} {h} eq-fg eq-gh = record
{ shape-eq = λ s → trans (FG.shape-eq s) (GH.shape-eq s)
; pos-eq = λ s p → begin
F.position {s} p
≡⟨ FG.pos-eq s p ⟩
G.position {s} (subst (Position D) (FG.shape-eq s) p)
≡⟨ GH.pos-eq s (subst (Position D) (FG.shape-eq s) p) ⟩
H.position {s} (subst (Position D) (GH.shape-eq s) (subst (Position D) (FG.shape-eq s) p))
≡⟨ cong (H.position {s}) (subst-subst (FG.shape-eq s) {y≡z = GH.shape-eq s}) ⟩
H.position {s} (subst (Position D) (trans (FG.shape-eq s) (GH.shape-eq s)) p)
∎
}
where
module F = _⇒_ f
module G = _⇒_ g
module H = _⇒_ h
module FG = _≈M_ eq-fg
module GH = _≈M_ eq-gh
≈M-isEquiv : ∀ {s p} {C D : Container s p} → IsEquivalence (_≈M_ {s} {p} {C} {D})
≈M-isEquiv = record
{ refl = ≈M-refl
; sym = ≈M-sym
; trans = ≈M-trans
}
module ≈M-Reasoning {s p} {C D : Container s p} where
open import Relation.Binary.Reasoning.Setoid (record
{ Carrier = C ⇒ D
; _≈_ = _≈M_ {s} {p} {C} {D}
; isEquivalence = ≈M-isEquiv
}) public
∘M-assoc : ∀ {s p} {A B C D : Container s p}
{f : A ⇒ B} {g : B ⇒ C} {h : C ⇒ D}
→ (h ∘ g) ∘ f ≈M h ∘ (g ∘ f)
∘M-assoc = record { shape-eq = λ _ → refl ; pos-eq = λ _ _ → refl }
∘M-identityˡ : ∀ {s p} {A B : Container s p} {f : A ⇒ B} → id B ∘ f ≈M f
∘M-identityˡ = record { shape-eq = λ _ → refl ; pos-eq = λ _ _ → refl }
∘M-identityʳ : ∀ {s p} {A B : Container s p} {f : A ⇒ B} → f ∘ id A ≈M f
∘M-identityʳ = record { shape-eq = λ _ → refl ; pos-eq = λ _ _ → refl }
∘M-resp-≈ : ∀ {s p} {A B C : Container s p}
{g₁ g₂ : B ⇒ C} {f₁ f₂ : A ⇒ B}
→ g₁ ≈M g₂ → f₁ ≈M f₂ → g₁ ∘ f₁ ≈M g₂ ∘ f₂
∘M-resp-≈ {s} {p} {A} {B} {C} {g₁} {g₂} {f₁} {f₂} eq-g eq-f = record
{ shape-eq = shape-compat
; pos-eq = λ s p → begin
F1.position {s} (G1.position {F1.shape s} p)
≡⟨ F.pos-eq s (G1.position {F1.shape s} p) ⟩
F2.position {s} (subst (Position B) (F.shape-eq s) (G1.position {F1.shape s} p))
≡⟨ cong (F2.position {s}) (cong (subst (Position B) (F.shape-eq s)) (G.pos-eq (F1.shape s) p)) ⟩
F2.position {s} (subst (Position B) (F.shape-eq s) (G2.position {F1.shape s} (subst (Position C) (G.shape-eq (F1.shape s)) p)))
≡⟨ cong (F2.position {s}) (swap-onPos (F.shape-eq s) (subst (Position C) (G.shape-eq (F1.shape s)) p)) ⟩
F2.position {s} (G2.position {F2.shape s} (subst (Position C) (cong G2.shape (F.shape-eq s)) (subst (Position C) (G.shape-eq (F1.shape s)) p)))
≡⟨ cong (F2.position {s}) (cong (G2.position {F2.shape s}) (subst-subst (G.shape-eq (F1.shape s)) {y≡z = cong G2.shape (F.shape-eq s)})) ⟩
F2.position {s} (G2.position {F2.shape s} (subst (Position C) (shape-compat s) p))
∎
}
where
module F1 = _⇒_ f₁
module F2 = _⇒_ f₂
module G1 = _⇒_ g₁
module G2 = _⇒_ g₂
module F = _≈M_ eq-f
module G = _≈M_ eq-g
shape-compat : ∀ (s : Shape A) → G1.shape (F1.shape s) ≡ G2.shape (F2.shape s)
shape-compat s = trans (G.shape-eq (F1.shape s)) (cong G2.shape (F.shape-eq s))
swap-onPos : ∀ {t₁ t₂ : Shape B} (eq : t₁ ≡ t₂) (q : Position C (G2.shape t₁))
→ subst (Position B) eq (G2.position {t₁} q)
≡ G2.position {t₂} (subst (Position C) (cong G2.shape eq) q)
swap-onPos refl q = refl
∘M-resp-≈ˡ : ∀ {s p} {A B C : Container s p} {g₁ g₂ : B ⇒ C} {f : A ⇒ B}
→ g₁ ≈M g₂ → g₁ ∘ f ≈M g₂ ∘ f
∘M-resp-≈ˡ {f = f} g₁≈g₂ = ∘M-resp-≈ g₁≈g₂ (≈M-refl {f = f})
∘M-resp-≈ʳ : ∀ {s p} {A B C : Container s p} {g : B ⇒ C} {f₁ f₂ : A ⇒ B}
→ f₁ ≈M f₂ → g ∘ f₁ ≈M g ∘ f₂
∘M-resp-≈ʳ {g = g} f₁≈f₂ = ∘M-resp-≈ (≈M-refl {f = g}) f₁≈f₂
ContCat : (s p : Level) → Category (lsuc s ⊔ lsuc p) (s ⊔ p) (s ⊔ p)
ContCat s p = record
{ Obj = Container s p
; _⇒_ = _⇒_
; _≈_ = _≈M_
; id = λ {A} → id A
; _∘_ = _∘_
; equiv = ≈M-isEquiv
; ∘-resp-≈ = ∘M-resp-≈
; assoc = λ {A B C D f g h} → ∘M-assoc {s} {p} {A} {B} {C} {D} {f} {g} {h}
; sym-assoc = λ {A B C D f g h} → ≈M-sym (∘M-assoc {s} {p} {A} {B} {C} {D} {f} {g} {h})
; identityˡ = ∘M-identityˡ
; identityʳ = ∘M-identityʳ
; identity² = λ {A} → ∘M-identityˡ {f = id A}
}