{-# OPTIONS --safe --cubical-compatible --guardedness --exact-split --double-check #-}
module ALMA.Base.Equivalence.SubstTransport where
open import Agda.Primitive using (Level; _⊔_)
open import Agda.Builtin.Equality using (_≡_; refl)
open import Data.Product.Base using (_×_; _,_; proj₁; proj₂)
open import Relation.Binary.PropositionalEquality.Core using (sym; trans; cong; subst)
open import Relation.Binary.Structures using (IsEquivalence)
open import Relation.Binary.PropositionalEquality.Properties using
(subst-subst; subst-subst-sym; subst-sym-subst; module ≡-Reasoning)
open ≡-Reasoning
open import ALMA.Base.Equivalence.Core using (_⊣_)
module _ {a b c d e : Level} {S : Set a} {T : Set c} (P : T → Set b)
(R : S → Set d) {F : Set e} (shape : F → S → T) where
module SubstTransport-Right
(pos : (f : F) → ∀ {s : S} → P (shape f s) → R s)
where
record _≈sr_ (f g : F) : Set (a ⊔ b ⊔ c ⊔ d) where
field
shape-eq : ∀ s → shape f s ≡ shape g s
position-eq : ∀ s (q : P (shape f s))
→ pos f q ≡ pos g (subst P (shape-eq s) q)
open _≈sr_
≈sr-refl : ∀ {f} → f ≈sr f
≈sr-refl = record
{ shape-eq = λ _ → refl
; position-eq = λ _ _ → refl
}
≈sr-sym : ∀ {f g} → f ≈sr g → g ≈sr f
≈sr-sym {f} {g} p = record
{ shape-eq = λ s → sym (p .shape-eq s)
; position-eq = λ s q →
let e = p .shape-eq s
in begin
pos g q
≡⟨ cong (pos g) (sym (subst-subst-sym {P = P} e {p = q})) ⟩
pos g (subst P e (subst P (sym e) q))
≡⟨ sym (p .position-eq s (subst P (sym e) q)) ⟩
pos f (subst P (sym e) q)
∎
}
≈sr-trans : ∀ {f g h} → f ≈sr g → g ≈sr h → f ≈sr h
≈sr-trans {f} {g} {h} p q = record
{ shape-eq = λ s → trans (p .shape-eq s) (q .shape-eq s)
; position-eq = λ s r →
let e₁ = p .shape-eq s
e₂ = q .shape-eq s
r₁ = subst P e₁ r
in begin
pos f r
≡⟨ p .position-eq s r ⟩
pos g r₁
≡⟨ q .position-eq s r₁ ⟩
pos h (subst P e₂ r₁)
≡⟨ cong (pos h) (subst-subst {P = P} e₁ {y≡z = e₂} {p = r}) ⟩
pos h (subst P (trans e₁ e₂) r)
∎
}
≈sr-isEquivalence : IsEquivalence _≈sr_
≈sr-isEquivalence = record
{ refl = ≈sr-refl
; sym = ≈sr-sym
; trans = ≈sr-trans
}
module ≈sr-Reasoning where
open import Relation.Binary.Reasoning.Setoid (record
{ Carrier = F
; _≈_ = _≈sr_
; isEquivalence = ≈sr-isEquivalence
}) public
module SubstTransport-Left
(pos : (f : F) → ∀ {s : S} → R s → P (shape f s))
where
record _≈sl_ (f g : F) : Set (a ⊔ b ⊔ c ⊔ d) where
field
shape-eq : ∀ s → shape f s ≡ shape g s
position-eq : ∀ s (q : R s)
→ subst P (shape-eq s) (pos f q) ≡ pos g q
open _≈sl_
≈sl-refl : ∀ {f} → f ≈sl f
≈sl-refl = record
{ shape-eq = λ _ → refl
; position-eq = λ _ _ → refl
}
≈sl-sym : ∀ {f g} → f ≈sl g → g ≈sl f
≈sl-sym {f} {g} p = record
{ shape-eq = λ s → sym (p .shape-eq s)
; position-eq = λ s q →
let e = p .shape-eq s
in begin
subst P (sym e) (pos g q)
≡⟨ sym (cong (subst P (sym e)) (p .position-eq s q)) ⟩
subst P (sym e) (subst P e (pos f q))
≡⟨ subst-sym-subst {P = P} e {p = pos f q} ⟩
pos f q
∎
}
≈sl-trans : ∀ {f g h} → f ≈sl g → g ≈sl h → f ≈sl h
≈sl-trans {f} {g} {h} p q = record
{ shape-eq = λ s → trans (p .shape-eq s) (q .shape-eq s)
; position-eq = λ s r →
let e₁ = p .shape-eq s
e₂ = q .shape-eq s
in begin
subst P (trans e₁ e₂) (pos f r)
≡⟨ sym (subst-subst {P = P} e₁ {y≡z = e₂} {p = pos f r}) ⟩
subst P e₂ (subst P e₁ (pos f r))
≡⟨ cong (subst P e₂) (p .position-eq s r) ⟩
subst P e₂ (pos g r)
≡⟨ q .position-eq s r ⟩
pos h r
∎
}
≈sl-isEquivalence : IsEquivalence _≈sl_
≈sl-isEquivalence = record
{ refl = ≈sl-refl
; sym = ≈sl-sym
; trans = ≈sl-trans
}
module ≈sl-Reasoning where
open import Relation.Binary.Reasoning.Setoid (record
{ Carrier = F
; _≈_ = _≈sl_
; isEquivalence = ≈sl-isEquivalence
}) public
module SubstTransport-Adjoint
(posL : (f : F) → ∀ {s : S} → R s → P (shape f s))
(posR : (f : F) → ∀ {s : S} → P (shape f s) → R s)
(adj : _⊣_ P R shape posL posR)
where
unit : ∀ f {s} (r : R s) → posR f (posL f r) ≡ r
unit = proj₁ adj
counit : ∀ f {s} (p : P (shape f s)) → posL f (posR f p) ≡ p
counit = proj₂ adj
open SubstTransport-Right posR using (_≈sr_; ≈sr-isEquivalence)
open SubstTransport-Left posL using (_≈sl_; ≈sl-isEquivalence)
≈R→≈L : ∀ {f g} → f ≈sr g → f ≈sl g
≈R→≈L {f} {g} p = record
{ shape-eq = _≈sr_.shape-eq p
; position-eq = λ s r →
let e = _≈sr_.shape-eq p s
h₁ = _≈sr_.position-eq p s (posL f r)
h₂ = unit f r
h₃ = counit g (subst P e (posL f r))
in begin
subst P e (posL f r)
≡⟨ sym h₃ ⟩
posL g (posR g (subst P e (posL f r)))
≡⟨ cong (posL g) (trans (sym h₁) h₂) ⟩
posL g r
∎
}
≈L→≈R : ∀ {f g} → f ≈sl g → f ≈sr g
≈L→≈R {f} {g} p = record
{ shape-eq = _≈sl_.shape-eq p
; position-eq = λ s q →
let e = _≈sl_.shape-eq p s
h₁ = _≈sl_.position-eq p s (posR f q)
h₂ = counit f q
h₃ = unit g (posR f q)
in begin
posR f q
≡⟨ sym h₃ ⟩
posR g (posL g (posR f q))
≡⟨ cong (posR g) (trans (sym h₁) (cong (subst P e) h₂)) ⟩
posR g (subst P e q)
∎
}
≈R↔≈L : ∀ {f g} → (f ≈sr g → f ≈sl g) × (f ≈sl g → f ≈sr g)
≈R↔≈L = ≈R→≈L , ≈L→≈R