Other Agda modules in this section (34)
- Equivalences
- Factorizations
- Identifications.EndpointTransport
- Identifications.FunctorCoherence
- Identifications.IdentificationSquares
- Identifications.Inverses
- Identifications.OverBase
- Identifications.ProjectedFactorization
- Identifications.RestrictionDiagrams
- Identifications.RetractionCoherence
- Identifications.SectionEvaluation
- Identifications.TriangleCoherence
- Identifications.Triangles
- ProductConstructions
- Products.BinaryFunctors
- Products.Equivalences
- Products.PairedVertexFrames
- Products.Pairing
- Products.PairingOverBase
- Products.PairingRestriction
- Products.PairingSquares
- Products.ProductFunctor
- Products.ProductFunctorCoherence
- Products.ProductPairing
- Products.ProductPairingComposition
- Products.ProductPairingIdentity
- Products.ProductRestriction
- Products.TripleEvaluationOuterImage
- RelativeFunctors
- RetractLoops
- Retracts
- Squares
- Supporting
- WhiskeringEquivalence
Chapter 1, rebuild2, checked 14 October 2026 · source revision b982f5a.
# Substitution in the first product factor `productMap σ (id C)` changes the parameter of a product `P × C`. This module computes the composition identification `productMap-first-comp f σ` of two such functors through its coordinates, which are postcomposed square cells, and proves its compatibility with pair inputs, restriction, a binary functor, a further substitution (associativity) and units. The identity coordinate keeps the specified unitor `comp-unitˡ (id C)`; it is normalized only where a statement requires it. Each comparison of two identifications into a product is the compatibility of a paired evaluation along a restriction diagram: the coordinate evaluations are compatible, so their pairing is (PairingSquares). The diagrams are the restriction of a pair, the substitution applied to a pair, and two successive substitutions. The unit normalization is the naturality of a paired evaluation in its inputs, and the binary case postcomposes the pairing (BinaryFunctors). ```agda {-# OPTIONS --without-K #-} module SCT.VolumeI.Chapter01.Section03.Products.FirstFactorSubstitution where open import SCT.VolumeI.Chapter01.Section01.Vocabulary hiding (_=_) import SCT.VolumeI.Chapter01.Section01.Terms as Terms open Terms using (Equal) open Operations open import SCT.VolumeI.Chapter01.Section01.Terminal using (module Constructions) open Constructions open import SCT.VolumeI.Chapter01.Section02.Coherence using (id₌; comp-unitˡ; comp-unitʳ; comp-assoc; postWhisker-id₌; preWhisker-id₌; module Composition; module Boundaries) open Composition open Boundaries using (SquareCell₌) open import SCT.VolumeI.Chapter01.Section02.Products using (module Calculus) open Calculus open import SCT.VolumeI.Chapter01.Section02.Specialization open import SCT.VolumeI.Chapter01.Section03.ProductConstructions using (productMap; productMap-id; productMap-comp; module Associativity) open import SCT.VolumeI.Chapter01.Section03.Identifications.Inverses open import SCT.VolumeI.Chapter01.Section03.Identifications.FunctorCoherence using (left-unitor-comp; identity-unitors; postWhisker-id-One) open import SCT.VolumeI.Chapter01.Section03.Identifications.Triangles open import SCT.VolumeI.Chapter01.Section03.Identifications.TriangleCoherence using (post-triangle-change; post-triangle-comp; module FrameChange) open import SCT.VolumeI.Chapter01.Section03.Identifications.RestrictionDiagrams using (restriction-diagram; evaluation) open import SCT.VolumeI.Chapter01.Section03.Products.Pairing open import SCT.VolumeI.Chapter01.Section03.Products.PairingRestriction open import SCT.VolumeI.Chapter01.Section03.Products.PairingSquares using (pair-compatible-One) open import SCT.VolumeI.Chapter01.Section03.Products.ProductFunctor open import SCT.VolumeI.Chapter01.Section03.Products.ProductFunctorCoherence open import SCT.VolumeI.Chapter01.Section03.Products.ProductPairing open import SCT.VolumeI.Chapter01.Section03.Products.BinaryFunctors ``` ## Composition coordinates The coordinates of `productMap-first-comp f σ` are the postcomposed square cells `first` and `second` of the two projections; the identity coordinate carries the left unitor of `id C`. ```agda module _ {Γ : Context} where module Coordinates {Y X Z : CAT Γ} (C : CAT Γ) (f : MAP X Z) (σ : MAP Y X) where substitution : MAP (Y × C) (X × C) substitution = productMap σ (id C) first : ((f ∘ pr₁) ∘ substitution) =₁ ((f ∘ σ) ∘ pr₁) first = post-square-cell f pr₁ σ pr₁ substitution (pair-β₁ (σ ∘ pr₁) (id C ∘ pr₂)) second-before-unit : ((id C ∘ pr₂) ∘ substitution) =₁ ((id C ∘ id C) ∘ pr₂) second-before-unit = post-square-cell (id C) pr₂ (id C) pr₂ substitution (pair-β₂ (σ ∘ pr₁) (id C ∘ pr₂)) second : ((id C ∘ pr₂) ∘ substitution) =₁ (id C ∘ pr₂) second = (comp-unitˡ (id C) ▷ pr₂) ∙ second-before-unit normalized : (productMap f (id C) ∘ substitution) =₁ productMap (f ∘ σ) (id C) normalized = pair⁼ first second ∙ pair-pre (f ∘ pr₁) (id C ∘ pr₂) substitution normalization : productMap-first-comp {C = C} f σ =₂ normalized normalization = let firstUnit = id₌ (f ∘ σ) ▷ pr₁ secondUnit = comp-unitˡ (id C) ▷ pr₂ firstNormalization = comp₌-unitˡ-One first ∙ comp₌-cong (preWhisker-id₌ (f ∘ σ) pr₁) (id₌ first) pairedNormalization = pair⁼-cong firstNormalization (id₌ second) ∙ (pair⁼-comp firstUnit first secondUnit second-before-unit) ⁻¹ in comp₌-cong pairedNormalization (id₌ (pair-pre (f ∘ pr₁) (id C ∘ pr₂) substitution)) ∙ (comp₌-assoc (pair⁼ firstUnit secondUnit) (pair⁼ first second-before-unit) (pair-pre (f ∘ pr₁) (id C ∘ pr₂) substitution)) ⁻¹ projection₁ : SquareCell₌ (pr₁ ◁ productMap-first-comp {C = C} f σ) first (project-pair₁ (f ∘ pr₁) (id C ∘ pr₂) substitution) (pair-β₁ ((f ∘ σ) ∘ pr₁) (id C ∘ pr₂)) projection₁ = pair-evaluation-over₁-One (f ∘ pr₁) (id C ∘ pr₂) substitution first second ∙ comp₌-cong (id₌ (pair-β₁ ((f ∘ σ) ∘ pr₁) (id C ∘ pr₂))) (postWhisker pr₁ ◁ normalization) projection₂ : SquareCell₌ (pr₂ ◁ productMap-first-comp {C = C} f σ) second (project-pair₂ (f ∘ pr₁) (id C ∘ pr₂) substitution) (pair-β₂ ((f ∘ σ) ∘ pr₁) (id C ∘ pr₂)) projection₂ = pair-evaluation-over₂-One (f ∘ pr₁) (id C ∘ pr₂) substitution first second ∙ comp₌-cong (id₌ (pair-β₂ ((f ∘ σ) ∘ pr₁) (id C ∘ pr₂))) (postWhisker pr₂ ◁ normalization) ``` ## The identity coordinate The second coordinate is the second projection law followed by the left unitor of `pr₂`. It is compatible with a further substitution `τ`. ```agda module _ {Y X : CAT Γ} where open Terms.InContext X using (Term) second-normalization : {Z : CAT Γ} (C : CAT Γ) (f : MAP X Z) (σ : MAP Y X) → Coordinates.second C f σ =₂ (pair-β₂ (σ ∘ pr₁) (id C ∘ pr₂) ∙ (comp-unitˡ pr₂ ▷ productMap σ (id C))) second-normalization C f σ = post-square-cell-id pr₂ (id C) pr₂ (productMap σ (id C)) (pair-β₂ (σ ∘ pr₁) (id C ∘ pr₂)) module _ {W Y X : CAT Γ} where open Terms.InContext X using (Term) second-coordinate-assoc : {Z : CAT Γ} (C : CAT Γ) (f : MAP X Z) (σ : MAP Y X) (τ : MAP W Y) → (Coordinates.second C f (σ ∘ τ) ∙ (((id C ∘ pr₂) ◁ productMap-first-comp {C = C} σ τ) ∙ comp-assoc (productMap τ (id C)) (productMap σ (id C)) (id C ∘ pr₂))) =₂ ((id₌ (id C) ▷ pr₂) ∙ (Coordinates.second C (f ∘ σ) τ ∙ (Coordinates.second C f σ ▷ productMap τ (id C)))) second-coordinate-assoc C f σ τ = let s = productMap σ (id C) t = productMap τ (id C) st = productMap (σ ∘ τ) (id C) change = productMap-first-comp {C = C} σ τ b = pair-β₂ (σ ∘ pr₁) (id C ∘ pr₂) bst = pair-β₂ ((σ ∘ τ) ∘ pr₁) (id C ∘ pr₂) S = Coordinates.second C f σ T = Coordinates.second C (f ∘ σ) τ normalized = T ∙ (S ▷ t) composition = FrameChange.compatible s t st change (id C ∘ pr₂) pr₂ (id C ∘ pr₂) (id C ∘ pr₂) (comp-unitˡ pr₂) b bst S T (Coordinates.second C f (σ ∘ τ)) (second-normalization C f σ) (second-normalization C f (σ ∘ τ)) (Coordinates.projection₂ C σ τ) insertIdentity = (comp₌-unitˡ-One normalized ∙ comp₌-cong (preWhisker-id₌ (id C) pr₂) (id₌ normalized)) ⁻¹ in insertIdentity ∙ composition ``` ## Pair inputs and restriction Applied to a pair `pair p x`, `productMap f (id C)` gives `pair (f ∘ p) x`, with the unitor of `x` in the second coordinate. This comparison is compatible with restricting the pair. ```agda module _ {T : CAT Γ} where open Terms.InContext T using (Term) module PairInput {X Y C : CAT Γ} (f : MAP X Y) (p : Term X) (x : Term C) where first : ((f ∘ pr₁) ∘ pair p x) =₁ (f ∘ p) first = post-triangle f pr₁ (pair p x) (pair-β₁ p x) second : ((id C ∘ pr₂) ∘ pair p x) =₁ x second = comp-unitˡ x ∙ post-triangle (id C) pr₂ (pair p x) (pair-β₂ p x) at-pair : (productMap f (id C) ∘ pair p x) =₁ pair (f ∘ p) x at-pair = pair⁼ (id₌ (f ∘ p)) (comp-unitˡ x) ∙ productMap-pair f (id C) p x normalized : (productMap f (id C) ∘ pair p x) =₁ pair (f ∘ p) x normalized = pair⁼ first second ∙ pair-pre (f ∘ pr₁) (id C ∘ pr₂) (pair p x) normalization : at-pair =₂ normalized normalization = comp₌-cong (pair⁼-cong (comp₌-unitˡ-One first) (id₌ second) ∙ (pair⁼-comp (id₌ (f ∘ p)) first (comp-unitˡ x) (post-triangle (id C) pr₂ (pair p x) (pair-β₂ p x))) ⁻¹) (id₌ _) ∙ (comp₌-assoc (pair⁼ (id₌ (f ∘ p)) (comp-unitˡ x)) (pair⁼ first (post-triangle (id C) pr₂ (pair p x) (pair-β₂ p x))) (pair-pre (f ∘ pr₁) (id C ∘ pr₂) (pair p x))) ⁻¹ module _ {R T X : CAT Γ} where open Terms.InContext T using (Term) pair-input-first-restrict : {Y C : CAT Γ} (f : MAP X Y) (p : Term X) (x : Term C) (r : MAP R T) → (PairInput.first f (p ∘ r) (x ∘ r) ∙ (((f ∘ pr₁) ◁ pair-pre p x r) ∙ comp-assoc r (pair p x) (f ∘ pr₁))) =₂ (comp-assoc r p f ∙ (PairInput.first f p x ▷ r)) pair-input-first-restrict f p x r = comp₌-unitˡ-One _ ∙ (comp₌-cong (postWhisker-id₌ f (p ∘ r)) (id₌ _) ∙ post-triangle-change f pr₁ (pair p x) r (pair (p ∘ r) (x ∘ r)) (pair-pre p x r) (pair-β₁ p x) (pair-β₁ (p ∘ r) (x ∘ r)) (id₌ (p ∘ r)) ((comp₌-unitˡ-One _) ⁻¹ ∙ pair-pre-triangle₁ p x r)) pair-input-second-restrict : {Y C : CAT Γ} (f : MAP X Y) (p : Term X) (x : Term C) (r : MAP R T) → (PairInput.second f (p ∘ r) (x ∘ r) ∙ (((id C ∘ pr₂) ◁ pair-pre p x r) ∙ comp-assoc r (pair p x) (id C ∘ pr₂))) =₂ (PairInput.second f p x ▷ r) pair-input-second-restrict {C = C} f p x r = let before = post-triangle (id C) pr₂ (pair p x) (pair-β₂ p x) after = post-triangle (id C) pr₂ (pair (p ∘ r) (x ∘ r)) (pair-β₂ (p ∘ r) (x ∘ r)) change = ((id C ∘ pr₂) ◁ pair-pre p x r) ∙ comp-assoc r (pair p x) (id C ∘ pr₂) coordinate = comp₌-unitˡ-One _ ∙ (comp₌-cong (postWhisker-id₌ (id C) (x ∘ r)) (id₌ _) ∙ post-triangle-change (id C) pr₂ (pair p x) r (pair (p ∘ r) (x ∘ r)) (pair-pre p x r) (pair-β₂ p x) (pair-β₂ (p ∘ r) (x ∘ r)) (id₌ (x ∘ r)) ((comp₌-unitˡ-One _) ⁻¹ ∙ pair-pre-triangle₂ p x r)) in (preWhisker-comp₌ (comp-unitˡ x) before r) ⁻¹ ∙ (comp₌-cong (left-unitor-comp r x) (id₌ (before ▷ r)) ∙ ((comp₌-assoc (comp-unitˡ (x ∘ r)) (comp-assoc r x (id C)) (before ▷ r)) ⁻¹ ∙ (comp₌-cong (id₌ (comp-unitˡ (x ∘ r))) coordinate ∙ comp₌-assoc (comp-unitˡ (x ∘ r)) after change))) at-pair-restrict : {Y C : CAT Γ} (f : MAP X Y) (p : Term X) (x : Term C) (r : MAP R T) → (PairInput.at-pair f (p ∘ r) (x ∘ r) ∙ ((productMap f (id C) ◁ pair-pre p x r) ∙ comp-assoc r (pair p x) (productMap f (id C)))) =₂ (pair⁼ (comp-assoc r p f) (id₌ (x ∘ r)) ∙ (pair-pre (f ∘ p) x r ∙ (PairInput.at-pair f p x ▷ r))) at-pair-restrict {C = C} f p x r = let u = PairInput.first f p x v = PairInput.second f p x w = id₌ ((f ∘ p) ∘ r) z = id₌ (x ∘ r) a = PairInput.first f (p ∘ r) (x ∘ r) d = PairInput.second f (p ∘ r) (x ∘ r) η = comp-assoc r p f θ = id₌ (x ∘ r) base = pair-pre (f ∘ p) x r restriction = restriction-diagram (pair p x) r (pair (p ∘ r) (x ∘ r)) (pair-pre p x r) assembled = pair-compatible-One restriction (evaluation a u w η) (evaluation d v z θ) (comp₌-cong (id₌ η) ((comp₌-unitˡ-One (u ▷ r)) ⁻¹) ∙ pair-input-first-restrict f p x r) ((comp₌-unitˡ-One _) ⁻¹ ∙ ((comp₌-unitˡ-One (v ▷ r)) ⁻¹ ∙ pair-input-second-restrict f p x r)) long-normal = comp₌-cong (id₌ (pair⁼ η θ)) (comp₌-cong (comp₌-unitˡ-One base ∙ comp₌-cong (pair⁼-id-One ((f ∘ p) ∘ r) (x ∘ r)) (id₌ base)) (preWhisker r ◁ (PairInput.normalization f p x) ⁻¹)) in long-normal ∙ (assembled ∙ comp₌-cong (PairInput.normalization f (p ∘ r) (x ∘ r)) (id₌ _)) ``` ## Normalizing the identity coordinate Replacing `id C ∘ pr₂` by `pr₂` on both sides of `productMap-first-comp f σ` gives the paired evaluation of the first coordinate and the second projection law. ```agda module UnitNormalization {P Q X C : CAT Γ} (f : MAP P X) (σ : MAP Q P) where s : MAP (Q × C) (P × C) s = productMap σ (id C) change : (productMap f (id C) ∘ s) =₁ productMap (f ∘ σ) (id C) change = productMap-first-comp f σ before : productMap f (id C) =₁ pair (f ∘ pr₁) pr₂ before = pair⁼ (id₌ (f ∘ pr₁)) (comp-unitˡ pr₂) after : productMap (f ∘ σ) (id C) =₁ pair ((f ∘ σ) ∘ pr₁) pr₂ after = pair⁼ (id₌ ((f ∘ σ) ∘ pr₁)) (comp-unitˡ pr₂) first : ((f ∘ pr₁) ∘ s) =₁ (f ∘ (σ ∘ pr₁)) first = (f ◁ pair-β₁ (σ ∘ pr₁) (id C ∘ pr₂)) ∙ comp-assoc s pr₁ f second : (pr₂ ∘ s) =₁ pr₂ second = comp-unitˡ pr₂ ∙ pair-β₂ (σ ∘ pr₁) (id C ∘ pr₂) finish : pair ((f ∘ σ) ∘ pr₁) pr₂ =₁ pair (f ∘ (σ ∘ pr₁)) (pr₂ {C = Q} {D = C}) finish = pair⁼ (comp-assoc pr₁ σ f) (id₌ pr₂) changed : (pair (f ∘ pr₁) pr₂ ∘ s) =₁ pair (f ∘ (σ ∘ pr₁)) pr₂ changed = pair⁼ first second ∙ pair-pre (f ∘ pr₁) pr₂ s unit-square : ((finish ∙ after) ∙ change) =₂ (changed ∙ (before ▷ s)) unit-square = let A = comp-assoc pr₁ σ f e = Coordinates.first C f σ d = Coordinates.second C f σ unitBefore = comp-unitˡ pr₂ unitAfter = comp-unitˡ pr₂ firstNormalize = (comp₌-cong (id₌ first) (preWhisker-id₌ (f ∘ pr₁) s)) ⁻¹ ∙ ((comp₌-unitʳ-One first) ⁻¹ ∙ (comp-inv-left A first ∙ comp₌-cong (id₌ A) (comp₌-unitˡ-One e))) secondNormalize = (comp₌-assoc unitAfter (pair-β₂ (σ ∘ pr₁) (id C ∘ pr₂)) (unitBefore ▷ s)) ⁻¹ ∙ (comp₌-cong (id₌ unitAfter) (second-normalization C f σ) ∙ comp₌-unitˡ-One (unitAfter ∙ d)) firstSquare = (comp₌-assoc A (id₌ ((f ∘ σ) ∘ pr₁)) e) ⁻¹ ∙ firstNormalize ⁻¹ secondSquare = (comp₌-assoc (id₌ pr₂) unitAfter d) ⁻¹ ∙ secondNormalize ⁻¹ natural = pair-evaluation-natural-inputs-One (id₌ (f ∘ pr₁)) unitBefore s e first d second (A ∙ id₌ ((f ∘ σ) ∘ pr₁)) (id₌ pr₂ ∙ unitAfter) firstSquare secondSquare in natural ⁻¹ ∙ comp₌-cong ((pair⁼-comp A (id₌ ((f ∘ σ) ∘ pr₁)) (id₌ pr₂) unitAfter) ⁻¹) (Coordinates.normalization C f σ) ``` ## Changing both the first functor and the pair input ```agda module _ {T X : CAT Γ} where open Terms.InContext T using (Term) pair-input-second-normalization : {Y C : CAT Γ} (f : MAP X Y) (p : Term X) (x : Term C) → PairInput.second f p x =₂ (pair-β₂ p x ∙ (comp-unitˡ pr₂ ▷ pair p x)) pair-input-second-normalization {C = C} f p x = comp₌-cong (id₌ (pair-β₂ p x)) (left-unitor-comp (pair p x) pr₂) ∙ (comp₌-assoc (pair-β₂ p x) (comp-unitˡ (pr₂ ∘ pair p x)) (comp-assoc (pair p x) pr₂ (id C)) ∙ (comp₌-cong (postWhisker-id-One (pair-β₂ p x)) (id₌ (comp-assoc (pair p x) pr₂ (id C))) ∙ (comp₌-assoc (comp-unitˡ x) (id C ◁ pair-β₂ p x) (comp-assoc (pair p x) pr₂ (id C))) ⁻¹)) at-pair-projection₁ : {Y C : CAT Γ} (f : MAP X Y) (p : Term X) (x : Term C) → SquareCell₌ (pr₁ ◁ PairInput.at-pair f p x) (PairInput.first f p x) (project-pair₁ (f ∘ pr₁) (id C ∘ pr₂) (pair p x)) (pair-β₁ (f ∘ p) x) at-pair-projection₁ {C = C} f p x = pair-evaluation-over₁-One (f ∘ pr₁) (id C ∘ pr₂) (pair p x) (PairInput.first f p x) (PairInput.second f p x) ∙ comp₌-cong (id₌ (pair-β₁ (f ∘ p) x)) (postWhisker pr₁ ◁ PairInput.normalization f p x) at-pair-projection₂ : {Y C : CAT Γ} (f : MAP X Y) (p : Term X) (x : Term C) → SquareCell₌ (pr₂ ◁ PairInput.at-pair f p x) (PairInput.second f p x) (project-pair₂ (f ∘ pr₁) (id C ∘ pr₂) (pair p x)) (pair-β₂ (f ∘ p) x) at-pair-projection₂ {C = C} f p x = pair-evaluation-over₂-One (f ∘ pr₁) (id C ∘ pr₂) (pair p x) (PairInput.first f p x) (PairInput.second f p x) ∙ comp₌-cong (id₌ (pair-β₂ (f ∘ p) x)) (postWhisker pr₂ ◁ PairInput.normalization f p x) module _ {T : CAT Γ} where open Terms.InContext T using (Term) pair-input-first-change : {Q P Y C : CAT Γ} (f : MAP P Y) (σ : MAP Q P) (p : Term Q) (x : Term C) → (PairInput.first f (σ ∘ p) x ∙ (((f ∘ pr₁) ◁ PairInput.at-pair σ p x) ∙ comp-assoc (pair p x) (productMap σ (id C)) (f ∘ pr₁))) =₂ (comp-assoc p σ f ∙ (PairInput.first (f ∘ σ) p x ∙ (Coordinates.first C f σ ▷ pair p x))) pair-input-first-change {C = C} f σ p x = let h = productMap σ (id C) t = pair p x n = PairInput.at-pair σ p x b = pair-β₁ (σ ∘ pr₁) (id C ∘ pr₂) c = PairInput.first σ p x original = post-triangle f pr₁ h b u = Coordinates.first C f σ w = PairInput.first (f ∘ σ) p x A = comp-assoc p σ f corner = comp-assoc pr₁ σ f mid = comp-assoc t (σ ∘ pr₁) f simplify = (preWhisker t ◁ comp-inv-left corner original) ∙ (preWhisker-comp₌ corner u t) ⁻¹ normalizeLong = comp₌-cong (id₌ (f ◁ c)) (comp₌-cong (id₌ mid) simplify) ∙ (comp₌-cong (id₌ (f ◁ c)) (comp₌-assoc mid (corner ▷ t) (u ▷ t)) ∙ (comp₌-assoc (f ◁ c) (mid ∙ (corner ▷ t)) (u ▷ t) ∙ (comp₌-cong (post-triangle-comp f σ pr₁ t (pair-β₁ p x)) (id₌ (u ▷ t)) ∙ (comp₌-assoc A w (u ▷ t)) ⁻¹))) in normalizeLong ⁻¹ ∙ post-triangle-change f pr₁ h t (pair (σ ∘ p) x) n b (pair-β₁ (σ ∘ p) x) c (at-pair-projection₁ σ p x) pair-input-second-change : {Q P Y C : CAT Γ} (f : MAP P Y) (σ : MAP Q P) (p : Term Q) (x : Term C) → (PairInput.second f (σ ∘ p) x ∙ (((id C ∘ pr₂) ◁ PairInput.at-pair σ p x) ∙ comp-assoc (pair p x) (productMap σ (id C)) (id C ∘ pr₂))) =₂ (id₌ x ∙ (PairInput.second (f ∘ σ) p x ∙ (Coordinates.second C f σ ▷ pair p x))) pair-input-second-change {C = C} f σ p x = let h = productMap σ (id C) t = pair p x n = PairInput.at-pair σ p x S = Coordinates.second C f σ T = PairInput.second (f ∘ σ) p x normalized = T ∙ (S ▷ t) composition = FrameChange.compatible h t (pair (σ ∘ p) x) n (id C ∘ pr₂) pr₂ (id C ∘ pr₂) x (comp-unitˡ pr₂) (pair-β₂ (σ ∘ pr₁) (id C ∘ pr₂)) (pair-β₂ (σ ∘ p) x) S T (PairInput.second f (σ ∘ p) x) (second-normalization C f σ) (pair-input-second-normalization f (σ ∘ p) x) (at-pair-projection₂ σ p x) in (comp₌-unitˡ-One normalized) ⁻¹ ∙ composition at-pair-input-change : {Q P Y C : CAT Γ} (f : MAP P Y) (σ : MAP Q P) (p : Term Q) (x : Term C) → (PairInput.at-pair f (σ ∘ p) x ∙ ((productMap f (id C) ◁ PairInput.at-pair σ p x) ∙ comp-assoc (pair p x) (productMap σ (id C)) (productMap f (id C)))) =₂ (pair⁼ (comp-assoc p σ f) (id₌ x) ∙ (PairInput.at-pair (f ∘ σ) p x ∙ (productMap-first-comp {C = C} f σ ▷ pair p x))) at-pair-input-change {C = C} f σ p x = let u = Coordinates.first C f σ v = Coordinates.second C f σ w = PairInput.first (f ∘ σ) p x z = PairInput.second (f ∘ σ) p x a = PairInput.first f (σ ∘ p) x d = PairInput.second f (σ ∘ p) x η = comp-assoc p σ f θ = id₌ x substitution = restriction-diagram (productMap σ (id C)) (pair p x) (pair (σ ∘ p) x) (PairInput.at-pair σ p x) assembled = pair-compatible-One substitution (evaluation a u w η) (evaluation d v z θ) (pair-input-first-change f σ p x) (pair-input-second-change f σ p x) normalizeShort = comp₌-cong (PairInput.normalization f (σ ∘ p) x) (id₌ _) normalizeLong = comp₌-cong (id₌ (pair⁼ η θ)) (comp₌-cong (PairInput.normalization (f ∘ σ) p x) (preWhisker (pair p x) ◁ Coordinates.normalization C f σ)) in normalizeLong ⁻¹ ∙ (assembled ∙ normalizeShort) ``` ## The first coordinate of a binary functor For a binary functor `F`, restricting `binary-apply F g f` along the first projection is compatible with the substitution `productMap σ (id C)`. ```agda module _ {Γ : Context} where module BinaryFirstCoordinate {P Q A B Z : CAT Γ} (C : CAT Γ) (F : MAP (A × B) Z) (g : MAP P A) (f : MAP P B) (σ : MAP Q P) where s : MAP (Q × C) (P × C) s = productMap σ (id C) δ : (pr₁ ∘ s) =₁ (σ ∘ pr₁) δ = pair-β₁ (σ ∘ pr₁) (id C ∘ pr₂) first-associator : ((g ∘ σ) ∘ pr₁) =₁ (g ∘ (σ ∘ pr₁)) first-associator = comp-assoc (pr₁ {C = Q} {D = C}) σ g second-associator : ((f ∘ σ) ∘ pr₁) =₁ (f ∘ (σ ∘ pr₁)) second-associator = comp-assoc (pr₁ {C = Q} {D = C}) σ f output-associator : ((binary-apply F g f ∘ σ) ∘ pr₁) =₁ (binary-apply F g f ∘ (σ ∘ pr₁)) output-associator = comp-assoc (pr₁ {C = Q} {D = C}) σ (binary-apply F g f) first-coordinate : ((g ∘ pr₁) ∘ s) =₁ ((g ∘ σ) ∘ pr₁) first-coordinate = Coordinates.first C g σ second-coordinate : ((f ∘ pr₁) ∘ s) =₁ ((f ∘ σ) ∘ pr₁) second-coordinate = Coordinates.first C f σ output-coordinate : ((binary-apply F g f ∘ pr₁) ∘ s) =₁ ((binary-apply F g f ∘ σ) ∘ pr₁) output-coordinate = Coordinates.first C (binary-apply F g f) σ original-route : (binary-apply F g f ∘ pr₁) =₁ binary-apply F (g ∘ pr₁) (f ∘ pr₁) original-route = binary-cong F (id₌ (g ∘ pr₁ {C = P} {D = C})) (id₌ (f ∘ pr₁ {C = P} {D = C})) ∙ binary-pre F g f (pr₁ {C = P} {D = C}) changed-route : (binary-apply F g f ∘ (σ ∘ pr₁)) =₁ binary-apply F ((g ∘ σ) ∘ pr₁) ((f ∘ σ) ∘ pr₁) changed-route = binary-cong F (first-associator ⁻¹) (second-associator ⁻¹) ∙ binary-pre F g f (σ ∘ pr₁ {C = Q} {D = C}) tail : ((binary-apply F g f ∘ pr₁) ∘ s) =₁ (binary-apply F g f ∘ (σ ∘ pr₁)) tail = (binary-apply F g f ◁ δ) ∙ comp-assoc s pr₁ (binary-apply F g f) iterated-route : ((binary-apply F g f ∘ σ) ∘ pr₁) =₁ binary-apply F ((g ∘ σ) ∘ pr₁) ((f ∘ σ) ∘ pr₁) iterated-route = binary-pre F (g ∘ σ) (f ∘ σ) (pr₁ {C = Q} {D = C}) ∙ (binary-pre F g f σ ▷ pr₁ {C = Q} {D = C}) abstract old-normalization : original-route =₂ binary-pre F g f pr₁ old-normalization = comp₌-unitˡ-One (binary-pre F g f pr₁) ∙ comp₌-cong (binary-cong-id-One F (g ∘ pr₁) (f ∘ pr₁)) (id₌ (binary-pre F g f pr₁)) abstract new-normalization : changed-route =₂ (iterated-route ∙ output-associator ⁻¹) new-normalization = let inverseAction = binary-cong F (first-associator ⁻¹) (second-associator ⁻¹) forwardAction = binary-cong F first-associator second-associator cancelAction = binary-cong-id-One F ((g ∘ σ) ∘ pr₁) ((f ∘ σ) ∘ pr₁) ∙ (binary-cong₂ F (comp₌-inverseˡ-One first-associator) (comp₌-inverseˡ-One second-associator) ∙ (binary-cong-comp F (first-associator ⁻¹) first-associator (second-associator ⁻¹) second-associator) ⁻¹) square = comp₌-unitˡ-One iterated-route ∙ (comp₌-cong cancelAction (id₌ iterated-route) ∙ ((comp₌-assoc inverseAction forwardAction iterated-route) ⁻¹ ∙ (comp₌-cong (id₌ inverseAction) (binary-pre-iterated F g f σ pr₁) ∙ comp₌-assoc inverseAction (binary-pre F g f (σ ∘ pr₁)) output-associator))) in comp₌-cong square (id₌ (output-associator ⁻¹)) ∙ (comp-inv-right changed-route output-associator) ⁻¹ abstract compatibility : (binary-pre F (g ∘ σ) (f ∘ σ) pr₁ ∙ ((binary-pre F g f σ ▷ pr₁) ∙ output-coordinate)) =₂ (binary-cong F first-coordinate second-coordinate ∙ (binary-pre F (g ∘ pr₁) (f ∘ pr₁) s ∙ (binary-pre F g f pr₁ ▷ s))) compatibility = let first = (comp₌-unitʳ-One first-coordinate ∙ comp₌-cong (id₌ first-coordinate) (preWhisker-id₌ (g ∘ pr₁) s)) ⁻¹ second = (comp₌-unitʳ-One second-coordinate ∙ comp₌-cong (id₌ second-coordinate) (preWhisker-id₌ (f ∘ pr₁) s)) ⁻¹ restriction = restriction-diagram pr₁ s (σ ∘ pr₁) δ unstaged : {K : CAT Γ} (h : MAP P K) (c : ((h ∘ pr₁) ∘ s) =₁ ((h ∘ σ) ∘ pr₁)) → (c ∙ (id₌ ((h ∘ pr₁) ∘ s) ∙ (id₌ (h ∘ pr₁) ▷ s))) =₂ (c ∙ (id₌ (h ∘ pr₁) ▷ s)) unstaged h c = comp₌-cong (id₌ c) (comp₌-unitˡ-One (id₌ (h ∘ pr₁) ▷ s)) second-stage = binary-pre F (g ∘ pr₁) (f ∘ pr₁) s trivial-stage = comp₌-unitˡ-One second-stage ∙ comp₌-cong (binary-cong-id-One F ((g ∘ pr₁) ∘ s) ((f ∘ pr₁) ∘ s)) (id₌ second-stage) binary = binary-compatible restriction F (evaluation (first-associator ⁻¹) (id₌ (g ∘ pr₁)) (id₌ ((g ∘ pr₁) ∘ s)) first-coordinate) (evaluation (second-associator ⁻¹) (id₌ (f ∘ pr₁)) (id₌ ((f ∘ pr₁) ∘ s)) second-coordinate) ((unstaged g first-coordinate) ⁻¹ ∙ first) ((unstaged f second-coordinate) ⁻¹ ∙ second) assembled = comp₌-cong (id₌ (binary-cong F first-coordinate second-coordinate)) (comp₌-cong trivial-stage (id₌ _)) ∙ binary left = comp₌-cong (new-normalization ⁻¹) (id₌ tail) ∙ ((comp₌-assoc iterated-route (output-associator ⁻¹) tail) ⁻¹ ∙ (comp₌-assoc (binary-pre F (g ∘ σ) (f ∘ σ) pr₁) (binary-pre F g f σ ▷ pr₁) output-coordinate) ⁻¹) right = comp₌-cong (id₌ (binary-cong F first-coordinate second-coordinate)) (comp₌-cong (id₌ (binary-pre F (g ∘ pr₁) (f ∘ pr₁) s)) (preWhisker s ◁ old-normalization)) in right ∙ (assembled ∙ left) ``` ## Associativity Successive substitutions along `σ` and `τ` agree with the substitution along `σ ∘ τ`, compatibly with the comparisons. The first coordinate is a comparison of postcomposed square cells; the second keeps the unitor. ```agda module _ {Q R X : CAT Γ} where open Terms.InContext X using (Term) first-coordinate-assoc : {Z : CAT Γ} (C : CAT Γ) (f : MAP X Z) (σ : MAP R X) (τ : MAP Q R) → (Coordinates.first C f (σ ∘ τ) ∙ (((f ∘ pr₁) ◁ productMap-first-comp {C = C} σ τ) ∙ comp-assoc (productMap τ (id C)) (productMap σ (id C)) (f ∘ pr₁))) =₂ ((comp-assoc τ σ f ▷ pr₁) ∙ (Coordinates.first C (f ∘ σ) τ ∙ (Coordinates.first C f σ ▷ productMap τ (id C)))) first-coordinate-assoc C f σ τ = let h = productMap σ (id C) k = productMap τ (id C) l = productMap (σ ∘ τ) (id C) change = productMap-first-comp {C = C} σ τ b = pair-β₁ (σ ∘ pr₁) (id C ∘ pr₂) b′ = pair-β₁ ((σ ∘ τ) ∘ pr₁) (id C ∘ pr₂) c = Coordinates.first C σ τ outside = (comp-assoc pr₁ (σ ∘ τ) f) ⁻¹ leftImage = f ◁ b′ inputA = comp-assoc l pr₁ f image-change = (f ∘ pr₁) ◁ change sourceA = comp-assoc k h (f ∘ pr₁) normalizeShort = comp₌-cong (id₌ outside) (post-triangle-change f pr₁ h k l change b b′ c (Coordinates.projection₁ C σ τ)) ∙ comp₌-assoc outside (leftImage ∙ inputA) (image-change ∙ sourceA) u = Coordinates.first C f σ w = Coordinates.first C (f ∘ σ) τ delta = comp-assoc τ σ f ▷ pr₁ sourceCorner = comp-assoc pr₁ σ f imageBefore = (f ◁ b) ∙ comp-assoc h pr₁ f nextCoordinate = post-square-cell f pr₁ (σ ∘ τ) (σ ∘ pr₁) k c outerSquare = (post-square-cell-comp pr₁ τ pr₁ k (pair-β₁ (τ ∘ pr₁) (id C ∘ pr₂)) σ f) ⁻¹ simplifyCorner = (preWhisker k ◁ comp-inv-left sourceCorner imageBefore) ∙ (preWhisker-comp₌ sourceCorner u k) ⁻¹ normalizeLong = comp₌-cong (id₌ outside) (comp₌-assoc (f ◁ c) (comp-assoc k (σ ∘ pr₁) f) (imageBefore ▷ k)) ∙ (comp₌-assoc outside ((f ◁ c) ∙ comp-assoc k (σ ∘ pr₁) f) (imageBefore ▷ k) ∙ (comp₌-cong (id₌ nextCoordinate) simplifyCorner ∙ (comp₌-assoc nextCoordinate (sourceCorner ▷ k) (u ▷ k) ∙ (comp₌-cong outerSquare (id₌ (u ▷ k)) ∙ (comp₌-assoc delta w (u ▷ k)) ⁻¹)))) in normalizeLong ⁻¹ ∙ normalizeShort productMap-first-comp-assoc : {Z : CAT Γ} (C : CAT Γ) (f : MAP X Z) (σ : MAP R X) (τ : MAP Q R) → (productMap-first-comp {C = C} f (σ ∘ τ) ∙ ((productMap f (id C) ◁ productMap-first-comp {C = C} σ τ) ∙ comp-assoc (productMap τ (id C)) (productMap σ (id C)) (productMap f (id C)))) =₂ (productMap-cong (comp-assoc τ σ f) (id₌ (id C)) ∙ (productMap-first-comp {C = C} (f ∘ σ) τ ∙ (productMap-first-comp {C = C} f σ ▷ productMap τ (id C)))) productMap-first-comp-assoc C f σ τ = let h = productMap σ (id C) k = productMap τ (id C) l = productMap (σ ∘ τ) (id C) change = productMap-first-comp {C = C} σ τ sourceTail = (productMap f (id C) ◁ change) ∙ comp-assoc k h (productMap f (id C)) delta = productMap-cong (comp-assoc τ σ f) (id₌ (id C)) normalizeShort = comp₌-cong (Coordinates.normalization C f (σ ∘ τ)) (id₌ sourceTail) normalizeLong = comp₌-cong (id₌ delta) (comp₌-cong (Coordinates.normalization C (f ∘ σ) τ) (preWhisker k ◁ Coordinates.normalization C f σ)) successive = restriction-diagram h k l change first-evaluation = evaluation (Coordinates.first C f (σ ∘ τ)) (Coordinates.first C f σ) (Coordinates.first C (f ∘ σ) τ) (comp-assoc τ σ f ▷ pr₁) second-evaluation = evaluation (Coordinates.second C f (σ ∘ τ)) (Coordinates.second C f σ) (Coordinates.second C (f ∘ σ) τ) (id₌ (id C) ▷ pr₂) assembled = pair-compatible-One successive first-evaluation second-evaluation (first-coordinate-assoc C f σ τ) (second-coordinate-assoc C f σ τ) in normalizeLong ⁻¹ ∙ (assembled ∙ normalizeShort) ``` ## Unit laws The fixed identity coordinate is merged with the unit of the varying coordinate. The right unit uses the identification of the two unitors of `id K`. ```agda private module _ {X : CAT Γ} where open Terms.InContext X using (Term) merge-fixed-unit : {Y : CAT Γ} (K : CAT Γ) {x y : Term Y} (p : x =₁ y) → (productMap-cong p (id₌ (id K)) ∙ productMap-cong (id₌ x) (comp-unitˡ (id K))) =₂ productMap-cong p (comp-unitˡ (id K)) merge-fixed-unit K p = productMap-cong₂ (comp₌-unitʳ-One p) (comp₌-unitˡ-One (comp-unitˡ (id K))) ∙ (productMap-cong-comp p (id₌ _) (id₌ (id K)) (comp-unitˡ (id K))) ⁻¹ module _ {X : CAT Γ} where open Terms.InContext X using (Term) abstract productMap-first-comp-unitˡ : {Y : CAT Γ} (K : CAT Γ) (z : Term Y) → (productMap-cong (comp-unitˡ z) (id₌ (id K)) ∙ productMap-first-comp (id Y) z) =₂ (comp-unitˡ (productMap z (id K)) ∙ (productMap-id Y K ▷ productMap z (id K))) productMap-first-comp-unitˡ {Y} K z = productMap-unitˡ z (id K) ∙ (comp₌-cong (merge-fixed-unit K (comp-unitˡ z)) (id₌ (productMap-comp z (id Y) (id K) (id K))) ∙ (comp₌-assoc (productMap-cong (comp-unitˡ z) (id₌ (id K))) (productMap-cong (id₌ (id Y ∘ z)) (comp-unitˡ (id K))) (productMap-comp z (id Y) (id K) (id K))) ⁻¹) productMap-first-comp-unitʳ : {Y : CAT Γ} (K : CAT Γ) (z : Term Y) → (productMap-cong (comp-unitʳ z) (id₌ (id K)) ∙ productMap-first-comp z (id X)) =₂ (comp-unitʳ (productMap z (id K)) ∙ (productMap z (id K) ◁ productMap-id X K)) productMap-first-comp-unitʳ {Y} K z = productMap-unitʳ z (id K) ∙ (comp₌-cong (productMap-cong₂ (id₌ (comp-unitʳ z)) ((identity-unitors K) ⁻¹) ∙ merge-fixed-unit K (comp-unitʳ z)) (id₌ (productMap-comp (id X) z (id K) (id K))) ∙ (comp₌-assoc (productMap-cong (comp-unitʳ z) (id₌ (id K))) (productMap-cong (id₌ (z ∘ id X)) (comp-unitˡ (id K))) (productMap-comp (id X) z (id K) (id K))) ⁻¹) ``` ## The projection pairing under a product functor Postcomposing `pair-projections` with a product functor gives `productMap-pair` at the projections, and the same holds for the identification `pair pr₁ z = id` built from `u : z = pr₂`. ```agda pair-projections-post : {A B C D : CAT Γ} (f : MAP A B) (g : MAP C D) → (comp-unitʳ (productMap f g) ∙ (productMap f g ◁ pair-projections)) =₂ productMap-pair f g pr₁ pr₂ pair-projections-post f g = let a = f ∘ pr₁ b = g ∘ pr₂ H = pair pr₁ pr₂ η = pair-projections left = comp-unitʳ a right = comp-unitʳ b first = a ◁ η second = b ◁ η outer = pair⁼ left right inner = pair⁼ first second pre = pair-pre a b H normalize = pair⁼-cong (identity-post-coordinate pr₁ f H η (pair-β₁ pr₁ pr₂) pair-projections-triangle₁) (identity-post-coordinate pr₂ g H η (pair-β₂ pr₁ pr₂) pair-projections-triangle₂) in comp₌-cong normalize (id₌ pre) ∙ (comp₌-cong ((pair⁼-comp left first right second) ⁻¹) (id₌ pre) ∙ ((comp₌-assoc outer inner pre) ⁻¹ ∙ (comp₌-cong (id₌ outer) (pair-pre-natural-substitution-One a b η) ∙ (comp₌-assoc outer (pair-pre a b (id _)) (productMap f g ◁ η) ∙ comp₌-cong ((pair-pre-id a b) ⁻¹) (id₌ (productMap f g ◁ η)))))) pair-pr₁-id-post : {P Q C : CAT Γ} (σ : MAP Q P) {x : MAP (Q × C) C} (u : x =₁ pr₂) → (comp-unitʳ (productMap σ (id C)) ∙ (productMap σ (id C) ◁ (pair-projections ∙ pair⁼ (id₌ pr₁) u))) =₂ (pair⁼ (id₌ (σ ∘ pr₁)) (id C ◁ u) ∙ productMap-pair σ (id C) pr₁ x) pair-pr₁-id-post {C = C} σ {x} u = let s = productMap σ (id C) η = pair-projections r = pair⁼ (id₌ pr₁) u in comp₌-cong (pair⁼-cong (postWhisker-id₌ σ pr₁) (id₌ (id C ◁ u))) (id₌ (productMap-pair σ (id C) pr₁ x)) ∙ (productMap-pair-inner-One σ (id C) (id₌ pr₁) u ∙ (comp₌-cong (pair-projections-post σ (id C)) (id₌ (s ◁ r)) ∙ ((comp₌-assoc (comp-unitʳ s) (s ◁ η) (s ◁ r)) ⁻¹ ∙ comp₌-cong (id₌ (comp-unitʳ s)) (postWhisker-comp₌ s η r)))) ``` ## Reassociation Changing the first factor of a triple product commutes with the associativity functors of ProductConstructions. Both comparisons are assembled from their coordinates. ```agda module _ {Γ : Context} {R Y X C : CAT Γ} (σ : MAP R Y) where private leftChange : MAP ((R × X) × C) ((Y × X) × C) leftChange = productMap (productMap σ (id X)) (id C) rightChange : MAP (R × (X × C)) (Y × (X × C)) rightChange = productMap σ (id (X × C)) forward-natural : (Associativity.forward Y X C ∘ leftChange) =₁ (rightChange ∘ Associativity.forward R X C) forward-natural = let first = project-product₁ σ (id X) pr₁ ∙ ((pr₁ ◁ pair-β₁ (productMap σ (id X) ∘ pr₁) (id C ∘ pr₂)) ∙ comp-assoc leftChange pr₁ pr₁) second = comp-unitˡ (pr₂ ∘ pr₁) ∙ (project-product₂ σ (id X) pr₁ ∙ ((pr₂ ◁ pair-β₁ (productMap σ (id X) ∘ pr₁) (id C ∘ pr₂)) ∙ comp-assoc leftChange pr₁ pr₂)) third = comp-unitˡ pr₂ ∙ pair-β₂ (productMap σ (id X) ∘ pr₁) (id C ∘ pr₂) left-normal = pair⁼ first (pair⁼ second third ∙ pair-pre (pr₂ ∘ pr₁) pr₂ leftChange) ∙ pair-pre (pr₁ ∘ pr₁) (pair (pr₂ ∘ pr₁) pr₂) leftChange right-normal = pair⁼ (id₌ (σ ∘ (pr₁ ∘ pr₁))) (comp-unitˡ (pair (pr₂ ∘ pr₁) pr₂)) ∙ productMap-pair σ (id (X × C)) (pr₁ ∘ pr₁) (pair (pr₂ ∘ pr₁) pr₂) in right-normal ⁻¹ ∙ left-normal backward-natural : (Associativity.backward Y X C ∘ rightChange) =₁ (leftChange ∘ Associativity.backward R X C) backward-natural = let first = pair-β₁ (σ ∘ pr₁) (id (X × C) ∘ pr₂) secondProjection = comp-unitˡ pr₂ ∙ pair-β₂ (σ ∘ pr₁) (id (X × C) ∘ pr₂) second = (pr₁ ◁ secondProjection) ∙ comp-assoc rightChange pr₂ pr₁ third = (pr₂ ◁ secondProjection) ∙ comp-assoc rightChange pr₂ pr₂ left-normal = pair⁼ (pair⁼ first second ∙ pair-pre pr₁ (pr₁ ∘ pr₂) rightChange) third ∙ pair-pre (pair pr₁ (pr₁ ∘ pr₂)) (pr₂ ∘ pr₂) rightChange right-normal = pair⁼ (pair⁼ (id₌ (σ ∘ pr₁)) (comp-unitˡ (pr₁ ∘ pr₂)) ∙ productMap-pair σ (id X) pr₁ (pr₁ ∘ pr₂)) (comp-unitˡ (pr₂ ∘ pr₂)) ∙ productMap-pair (productMap σ (id X)) (id C) (pair pr₁ (pr₁ ∘ pr₂)) (pr₂ ∘ pr₂) in right-normal ⁻¹ ∙ left-normal ```