diff --git a/src/Categories/Adjoint/Instance/Slice.agda b/src/Categories/Adjoint/Instance/Slice.agda index 818c161a0..3c99c3729 100644 --- a/src/Categories/Adjoint/Instance/Slice.agda +++ b/src/Categories/Adjoint/Instance/Slice.agda @@ -5,10 +5,18 @@ open import Categories.Category using (Category) module Categories.Adjoint.Instance.Slice {o ℓ e} (C : Category o ℓ e) where open import Categories.Adjoint using (_⊣_) -open import Categories.Category.Slice C using (SliceObj; Slice⇒; slicearr) -open import Categories.Functor.Slice C using (TotalSpace; ConstantFamily) +open import Categories.Category.BinaryProducts C +open import Categories.Category.Cartesian using (Cartesian) +open import Categories.Category.CartesianClosed using (CartesianClosed) +open import Categories.Category.Slice C using (SliceObj; sliceobj; Slice⇒; slicearr) +open import Categories.Functor.Slice C using (TotalSpace; ConstantFamily; InternalSections) +open import Categories.Morphism.Reasoning C open import Categories.NaturalTransformation using (ntHelper) +open import Categories.Diagram.Pullback C hiding (swap) open import Categories.Object.Product C +open import Categories.Object.Terminal C + +open import Function.Base using (_$_) open Category C open HomReasoning @@ -44,3 +52,93 @@ module _ {A : Obj} (product : ∀ {X} → Product A X) where ⟨ π₁ , π₂ ⟩ ≈⟨ η ⟩ id ∎ } + +module _ {A : Obj} (ccc : CartesianClosed C) (pullback : ∀ {X} {Y} {Z} (h : X ⇒ Z) (i : Y ⇒ Z) → Pullback h i) where + + open CartesianClosed ccc + open Cartesian cartesian + open Terminal terminal + open BinaryProducts products + + ConstantFamily⊣InternalSections : ConstantFamily {A = A} product ⊣ InternalSections ccc pullback + ConstantFamily⊣InternalSections = record + { unit = ntHelper record + { η = λ X → p.universal (sliceobj π₁) (λ-unique₂′ (unit-pb X)) + ; commute = λ {S} {T} f → p.unique-diagram (sliceobj π₁) !-unique₂ $ begin + p.p₂ (sliceobj π₁) ∘ p.universal (sliceobj π₁) _ ∘ f ≈⟨ pullˡ (p.p₂∘universal≈h₂ (sliceobj π₁)) ⟩ + λg swap ∘ f ≈⟨ subst ⟩ + λg (swap ∘ first f) ≈⟨ λ-cong swap∘⁂ ⟩ + λg (second f ∘ swap) ≈˘⟨ λ-cong (∘-resp-≈ʳ β′) ⟩ + λg (second f ∘ eval′ ∘ first (λg swap)) ≈˘⟨ λ-cong (∘-resp-≈ʳ (∘-resp-≈ʳ (first-cong (p.p₂∘universal≈h₂ (sliceobj π₁))))) ⟩ + λg (second f ∘ eval′ ∘ first (p.p₂ (sliceobj π₁) ∘ p.universal (sliceobj π₁) _)) ≈˘⟨ λ-cong (pull-last first∘first) ⟩ + λg ((second f ∘ eval′ ∘ first (p.p₂ (sliceobj π₁))) ∘ first (p.universal (sliceobj π₁) _)) ≈˘⟨ subst ⟩ + λg (second f ∘ eval′ ∘ first (p.p₂ (sliceobj π₁))) ∘ p.universal (sliceobj π₁) _ ≈˘⟨ pullˡ (p.p₂∘universal≈h₂ (sliceobj π₁)) ⟩ + p.p₂ (sliceobj π₁) ∘ p.universal (sliceobj π₁) _ ∘ p.universal (sliceobj π₁) _ ∎ + } + ; counit = ntHelper record + { η = λ X → slicearr (counit-△ X) + ; commute = λ {S} {T} f → begin + (eval′ ∘ first (p.p₂ T) ∘ swap) ∘ second (p.universal T _) ≈⟨ pull-last swap∘⁂ ⟩ + eval′ ∘ first (p.p₂ T) ∘ first (p.universal T _) ∘ swap ≈⟨ refl⟩∘⟨ pullˡ first∘first ⟩ + eval′ ∘ first (p.p₂ T ∘ p.universal T _) ∘ swap ≈⟨ refl⟩∘⟨ first-cong (p.p₂∘universal≈h₂ T) ⟩∘⟨refl ⟩ + eval′ ∘ first (λg (h f ∘ eval′ ∘ first (p.p₂ S))) ∘ swap ≈⟨ pullˡ β′ ⟩ + (h f ∘ eval′ ∘ first (p.p₂ S)) ∘ swap ≈⟨ assoc²βε ⟩ + h f ∘ eval′ ∘ first (p.p₂ S) ∘ swap ∎ + } + ; zig = λ {X} → begin + (eval′ ∘ first (p.p₂ (sliceobj π₁)) ∘ swap) ∘ second (p.universal (sliceobj π₁) _) ≈⟨ assoc²βε ⟩ + eval′ ∘ first (p.p₂ (sliceobj π₁)) ∘ swap ∘ second (p.universal (sliceobj π₁) _) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ swap∘⁂ ⟩ + eval′ ∘ first (p.p₂ (sliceobj π₁)) ∘ first (p.universal (sliceobj π₁) _) ∘ swap ≈⟨ refl⟩∘⟨ pullˡ first∘first ⟩ + eval′ ∘ first (p.p₂ (sliceobj π₁) ∘ p.universal (sliceobj π₁) _) ∘ swap ≈⟨ refl⟩∘⟨ first-cong (p.p₂∘universal≈h₂ (sliceobj π₁)) ⟩∘⟨refl ⟩ + eval′ ∘ first (λg swap) ∘ swap ≈⟨ pullˡ β′ ⟩ + swap ∘ swap ≈⟨ swap∘swap ⟩ + id ∎ + ; zag = λ {X} → p.unique-diagram X !-unique₂ $ begin + p.p₂ X ∘ p.universal X _ ∘ p.universal (sliceobj π₁) _ ≈⟨ pullˡ (p.p₂∘universal≈h₂ X) ⟩ + λg ((eval′ ∘ first (p.p₂ X) ∘ swap) ∘ eval′ ∘ first (p.p₂ (sliceobj π₁))) ∘ p.universal (sliceobj π₁) _ ≈˘⟨ pullˡ (subst ○ λ-cong assoc) ⟩ + λg ((eval′ ∘ first (p.p₂ X) ∘ swap) ∘ eval′) ∘ p.p₂ (sliceobj π₁) ∘ p.universal (sliceobj π₁) _ ≈⟨ refl⟩∘⟨ p.p₂∘universal≈h₂ (sliceobj π₁) ⟩ + λg ((eval′ ∘ first (p.p₂ X) ∘ swap) ∘ eval′) ∘ λg swap ≈⟨ subst ⟩ + λg (((eval′ ∘ first (p.p₂ X) ∘ swap) ∘ eval′) ∘ first (λg swap)) ≈⟨ λ-cong (pullʳ β′) ⟩ + λg ((eval′ ∘ first (p.p₂ X) ∘ swap) ∘ swap) ≈⟨ λ-cong (pullʳ (cancelʳ swap∘swap)) ⟩ + λg (eval′ ∘ first (p.p₂ X)) ≈⟨ η-exp′ ⟩ + p.p₂ X ≈˘⟨ identityʳ ⟩ + p.p₂ X ∘ id ∎ + } + where + p : (X : SliceObj A) → Pullback {X = ⊤} {Z = A ^ A} {Y = Y X ^ A} (λg π₂) (λg (arr X ∘ eval′)) + p X = pullback (λg π₂) (λg (arr X ∘ eval′)) + module p X = Pullback (p X) + + abstract + unit-pb : ∀ (X : Obj) → eval′ ∘ first {A = X} {C = A} (λg π₂ ∘ !) ≈ eval′ ∘ first (λg (π₁ ∘ eval′) ∘ λg swap) + unit-pb X = begin + eval′ ∘ first (λg π₂ ∘ !) ≈˘⟨ refl⟩∘⟨ first∘first ⟩ + eval′ ∘ first (λg π₂) ∘ first ! ≈⟨ pullˡ β′ ⟩ + π₂ ∘ first ! ≈⟨ π₂∘⁂ ○ identityˡ ⟩ + π₂ ≈˘⟨ project₁ ⟩ + π₁ ∘ swap ≈˘⟨ refl⟩∘⟨ β′ ⟩ + π₁ ∘ eval′ ∘ first (λg swap) ≈˘⟨ extendʳ β′ ⟩ + eval′ ∘ first (λg (π₁ ∘ eval′)) ∘ first (λg swap) ≈⟨ refl⟩∘⟨ first∘first ⟩ + eval′ ∘ first (λg (π₁ ∘ eval′) ∘ λg swap) ∎ + -- A good chunk of the above, maybe all if you squint, is duplicated with F₁-lemma + -- eval′ ∘ first (λg π₂ ∘ !) ≈ eval′ ∘ first (λg (f ∘ eval′) ∘ first (λg g) + -- With f : X ⇒ Y and g : Z × Y ⇒ X. Not sure what conditions f and g need to have + + -- Would it be better if Free used π₂ rather than π₁? + -- It would mean we could avoid this swap + counit-△ : ∀ X → arr X ∘ eval′ ∘ first (p.p₂ X) ∘ swap ≈ π₁ + counit-△ X = begin + arr X ∘ eval′ ∘ first (p.p₂ X) ∘ swap ≈˘⟨ assoc²αε ⟩ + ((arr X ∘ eval′) ∘ first (p.p₂ X)) ∘ swap ≈⟨ lemma ⟩∘⟨refl ⟩ + (π₂ ∘ first (p.p₁ X)) ∘ swap ≈⟨ (π₂∘⁂ ○ identityˡ) ⟩∘⟨refl ⟩ + π₂ ∘ swap ≈⟨ project₂ ⟩ + π₁ ∎ + where + lemma : (arr X ∘ eval′) ∘ first (p.p₂ X) ≈ π₂ ∘ first (p.p₁ X) + lemma = λ-inj $ begin + λg ((arr X ∘ eval′) ∘ first (p.p₂ X)) ≈˘⟨ subst ⟩ + λg (arr X ∘ eval′) ∘ p.p₂ X ≈˘⟨ p.commute X ⟩ + λg π₂ ∘ p.p₁ X ≈⟨ subst ⟩ + λg (π₂ ∘ first (p.p₁ X)) ∎ + + diff --git a/src/Categories/Category/BinaryProducts.agda b/src/Categories/Category/BinaryProducts.agda index 1b0cc33b3..3f5907a74 100644 --- a/src/Categories/Category/BinaryProducts.agda +++ b/src/Categories/Category/BinaryProducts.agda @@ -94,6 +94,12 @@ record BinaryProducts : Set (levelOfTerm 𝒞) where ⁂-cong₂ : f ≈ g → h ≈ i → f ⁂ h ≈ g ⁂ i ⁂-cong₂ = [ product ⇒ product ]×-cong₂ + first-cong : f ≈ g → f ⁂ h ≈ g ⁂ h + first-cong f≈g = ⁂-cong₂ f≈g Equiv.refl + + second-cong : g ≈ h → f ⁂ g ≈ f ⁂ h + second-cong g≈h = ⁂-cong₂ Equiv.refl g≈h + ⁂∘⟨⟩ : (f ⁂ g) ∘ ⟨ f′ , g′ ⟩ ≈ ⟨ f ∘ f′ , g ∘ g′ ⟩ ⁂∘⟨⟩ = [ product ⇒ product ]×∘⟨⟩ diff --git a/src/Categories/Category/CartesianClosed.agda b/src/Categories/Category/CartesianClosed.agda index 8f35da80f..6eae77356 100644 --- a/src/Categories/Category/CartesianClosed.agda +++ b/src/Categories/Category/CartesianClosed.agda @@ -56,7 +56,7 @@ record CartesianClosed : Set (levelOfTerm 𝒞) where open CartesianMonoidal cartesian using (A×⊤≅A) open BinaryProducts cartesian.products using (_×_; product; π₁; π₂; ⟨_,_⟩; project₁; project₂; η; ⟨⟩-cong₂; ⟨⟩∘; _⁂_; ⟨⟩-congˡ; ⟨⟩-congʳ; - first∘first; firstid; first; second; first↔second; second∘second; ⁂-cong₂; -×_) + first∘first; firstid; first; second; first↔second; second∘second; second-cong; -×_) open Terminal cartesian.terminal using (⊤; !; !-unique₂; ⊤-id) B^A×A : ∀ B A → Product (B ^ A) A @@ -194,7 +194,7 @@ record CartesianClosed : Set (levelOfTerm 𝒞) where ; identity = λ-cong (identityˡ ○ (elimʳ (id×id product))) ○ η-id′ ; homomorphism = λ-unique₂′ helper ; F-resp-≈ = λ where - (eq₁ , eq₂) → λ-cong (∘-resp-≈ eq₂ (∘-resp-≈ʳ (⁂-cong₂ refl eq₁))) + (eq₁ , eq₂) → λ-cong (∘-resp-≈ eq₂ (∘-resp-≈ʳ (second-cong eq₁))) } where helper : eval′ ∘ first (λg ((g ∘ f) ∘ eval′ ∘ second (h ∘ i))) ≈ eval′ ∘ first (λg (g ∘ eval′ ∘ second i) ∘ λg (f ∘ eval′ ∘ second h)) diff --git a/src/Categories/Category/Construction/Properties/Presheaves/FromCartesianCCC.agda b/src/Categories/Category/Construction/Properties/Presheaves/FromCartesianCCC.agda index 38adf7b1a..4a0f62171 100644 --- a/src/Categories/Category/Construction/Properties/Presheaves/FromCartesianCCC.agda +++ b/src/Categories/Category/Construction/Properties/Presheaves/FromCartesianCCC.agda @@ -55,7 +55,7 @@ module FromCartesian o′ ℓ′ {o ℓ e} {C : Category o ℓ e} (Car : Cartesi in begin F.₁ (second (f C.∘ g)) ⟨$⟩ x ≈˘⟨ [ F ]-resp-∘ second∘second ⟩ F.₁ (second g) ⟨$⟩ (F.₁ (second f) ⟨$⟩ x) ∎ - ; F-resp-≈ = λ {Y Z} {f g} eq → F.F-resp-≈ (⁂-cong₂ C.Equiv.refl eq) + ; F-resp-≈ = λ {Y Z} {f g} eq → F.F-resp-≈ (second-cong eq) } where module F = Functor F @@ -79,7 +79,7 @@ module FromCartesian o′ ℓ′ {o ℓ e} {C : Category o ℓ e} (Car : Cartesi in begin F₁ (first (f C.∘ g)) ⟨$⟩ x ≈˘⟨ [ F ]-resp-∘ first∘first ⟩ F₁ (first g) ⟨$⟩ (F₁ (first f) ⟨$⟩ x) ∎ - ; F-resp-≈ = λ {A B} {f g} eq → F-resp-≈ (⁂-cong₂ eq C.Equiv.refl) + ; F-resp-≈ = λ {A B} {f g} eq → F-resp-≈ (first-cong eq) } where open Functor F @@ -113,7 +113,7 @@ module FromCartesian o′ ℓ′ {o ℓ e} {C : Category o ℓ e} (Car : Cartesi F.₁ C.id ⟨$⟩ (α.η Y ⟨$⟩ x) ≈⟨ F.identity ⟩ α.η Y ⟨$⟩ x ∎ ; homomorphism = λ {X Y Z} → Setoid.sym (F.₀ (Z × _)) ([ F ]-resp-∘ first∘first) - ; F-resp-≈ = λ eq → F.F-resp-≈ (⁂-cong₂ eq C.Equiv.refl) + ; F-resp-≈ = λ eq → F.F-resp-≈ (first-cong eq) } module FromCartesianCCC {o} {C : Category o o o} (Car : Cartesian C) where diff --git a/src/Categories/Category/Construction/Pullbacks.agda b/src/Categories/Category/Construction/Pullbacks.agda index 54138bdc6..212aee570 100644 --- a/src/Categories/Category/Construction/Pullbacks.agda +++ b/src/Categories/Category/Construction/Pullbacks.agda @@ -33,12 +33,16 @@ record Pullback⇒ W (X Y : PullbackObj W) : Set (o ⊔ ℓ ⊔ e) where commute₁ : Y.arr₁ ∘ mor₁ ≈ X.arr₁ commute₂ : Y.arr₂ ∘ mor₂ ≈ X.arr₂ + private abstract + pbarrlemma : Y.arr₁ ∘ mor₁ ∘ X.pullback.p₁ ≈ Y.arr₂ ∘ mor₂ ∘ X.pullback.p₂ + pbarrlemma = begin + Y.arr₁ ∘ mor₁ ∘ X.pullback.p₁ ≈⟨ pullˡ commute₁ ⟩ + X.arr₁ ∘ X.pullback.p₁ ≈⟨ X.pullback.commute ⟩ + X.arr₂ ∘ X.pullback.p₂ ≈˘⟨ pullˡ commute₂ ⟩ + Y.arr₂ ∘ mor₂ ∘ X.pullback.p₂ ∎ + pbarr : X.pullback.P ⇒ Y.pullback.P - pbarr = Y.pullback.universal $ begin - Y.arr₁ ∘ mor₁ ∘ X.pullback.p₁ ≈⟨ pullˡ commute₁ ⟩ - X.arr₁ ∘ X.pullback.p₁ ≈⟨ X.pullback.commute ⟩ - X.arr₂ ∘ X.pullback.p₂ ≈˘⟨ pullˡ commute₂ ⟩ - Y.arr₂ ∘ mor₂ ∘ X.pullback.p₂ ∎ + pbarr = Y.pullback.universal pbarrlemma open Pullback⇒ diff --git a/src/Categories/Functor/Slice.agda b/src/Categories/Functor/Slice.agda index 6e66c39a6..06d098270 100644 --- a/src/Categories/Functor/Slice.agda +++ b/src/Categories/Functor/Slice.agda @@ -4,16 +4,22 @@ open import Categories.Category using (Category) module Categories.Functor.Slice {o ℓ e} (C : Category o ℓ e) where -open import Function using () renaming (id to id→) +open import Function.Base using (_$_) renaming (id to id→) +open import Categories.Category.BinaryProducts +open import Categories.Category.Cartesian +open import Categories.Category.CartesianClosed C open import Categories.Diagram.Pullback C using (Pullback; unglue; Pullback-resp-≈) open import Categories.Functor using (Functor) open import Categories.Functor.Properties using ([_]-resp-∘) open import Categories.Morphism.Reasoning C +open import Categories.Object.Exponential C open import Categories.Object.Product C +open import Categories.Object.Terminal C import Categories.Category.Slice as S import Categories.Category.Construction.Pullbacks as Pbs +import Categories.Object.Product.Construction as ×C open Category C open HomReasoning @@ -61,3 +67,57 @@ module _ {A : Obj} where ; F-resp-≈ = λ f≈g → ⟨⟩-cong₂ refl (∘-resp-≈ˡ f≈g) } + -- This can and probably should be restricted + -- e.g. we only need exponential objects with A as domain + -- I don't think we need all products but I don't have a clear idea of what products we do need + module _ (ccc : CartesianClosed) (pullback : ∀ {X} {Y} {Z} (h : X ⇒ Z) (i : Y ⇒ Z) → Pullback h i) where + + open CartesianClosed ccc + open Cartesian cartesian + open Terminal terminal + open BinaryProducts products + + InternalSections : Functor (Slice A) C + InternalSections = record + { F₀ = p.P + ; F₁ = λ f → p.universal _ (F₁-lemma f) + ; identity = λ {X} → sym $ p.unique X (sym (!-unique _)) $ begin + p.p₂ X ∘ id ≈⟨ identityʳ ⟩ + p.p₂ X ≈˘⟨ η-exp′ ⟩ + λg (eval′ ∘ first (p.p₂ X)) ≈˘⟨ λ-cong (pullˡ identityˡ) ⟩ + λg (id ∘ eval′ ∘ first (p.p₂ X)) ∎ + ; homomorphism = λ {S} {T} {U} {f} {g} → sym $ p.unique U (sym (!-unique _)) $ begin + p.p₂ U ∘ p.universal U (F₁-lemma g) ∘ p.universal T (F₁-lemma f) ≈⟨ pullˡ (p.p₂∘universal≈h₂ U) ⟩ + λg (h g ∘ eval′ ∘ first (p.p₂ T)) ∘ p.universal T (F₁-lemma f) ≈˘⟨ pullˡ (subst ○ λ-cong assoc) ⟩ + λg (h g ∘ eval′) ∘ p.p₂ T ∘ p.universal T (F₁-lemma f) ≈⟨ refl⟩∘⟨ p.p₂∘universal≈h₂ T ⟩ + λg (h g ∘ eval′) ∘ λg (h f ∘ eval′ ∘ first (p.p₂ S)) ≈⟨ subst ⟩ + λg ((h g ∘ eval′) ∘ first (λg (h f ∘ eval′ ∘ first (p.p₂ S)))) ≈⟨ λ-cong (pullʳ β′) ⟩ + λg (h g ∘ (h f ∘ eval′ ∘ first (p.p₂ S))) ≈⟨ λ-cong sym-assoc ⟩ + λg ((h g ∘ h f) ∘ eval′ ∘ first (p.p₂ S)) ∎ + ; F-resp-≈ = λ f≈g → p.universal-resp-≈ _ refl (λ-cong (∘-resp-≈ˡ f≈g)) + } + where + p : (X : SliceObj A) → Pullback {X = ⊤} {Z = A ^ A} {Y = Y X ^ A} (λg π₂) (λg (arr X ∘ eval′)) + p X = pullback (λg π₂) (λg (arr X ∘ eval′)) + module p X = Pullback (p X) + + abstract + F₁-lemma : ∀ {S} {T} (f : Slice⇒ S T) → λg π₂ ∘ ! ≈ λg (arr T ∘ eval′) ∘ λg (h f ∘ eval′ ∘ first (p.p₂ S)) + F₁-lemma {S} {T} f = λ-unique₂′ $ begin + eval′ ∘ first (λg π₂ ∘ !) ≈˘⟨ refl⟩∘⟨ first∘first ⟩ + eval′ ∘ first (λg π₂) ∘ first ! ≈⟨ pullˡ β′ ⟩ + π₂ ∘ first ! ≈⟨ π₂∘⁂ ○ identityˡ ⟩ + π₂ ≈⟨ λ-inj lemma ⟩ + arr S ∘ eval′ ∘ first (p.p₂ S) ≈˘⟨ pullˡ (△ f) ⟩ + arr T ∘ h f ∘ eval′ ∘ first (p.p₂ S) ≈˘⟨ pullʳ β′ ⟩ + (arr T ∘ eval′) ∘ first (λg (h f ∘ eval′ ∘ first (p.p₂ S))) ≈˘⟨ pullˡ β′ ⟩ + eval′ ∘ first (λg (arr T ∘ eval′)) ∘ first (λg (h f ∘ eval′ ∘ first (p.p₂ S))) ≈⟨ refl⟩∘⟨ first∘first ⟩ + eval′ ∘ first (λg (arr T ∘ eval′) ∘ λg (h f ∘ eval′ ∘ first (p.p₂ S))) ∎ + where + lemma : λg π₂ ≈ λg (arr S ∘ eval′ ∘ first (p.p₂ S)) + lemma = begin + λg π₂ ≈˘⟨ λ-cong (π₂∘⁂ ○ identityˡ) ⟩ + λg (π₂ ∘ first (p.p₁ S)) ≈˘⟨ subst ⟩ + λg π₂ ∘ p.p₁ S ≈⟨ p.commute S ⟩ + λg (arr S ∘ eval′) ∘ p.p₂ S ≈⟨ subst ○ λ-cong assoc ⟩ + λg (arr S ∘ eval′ ∘ first (p.p₂ S)) ∎ diff --git a/src/Categories/Object/NaturalNumbers/Properties/Parametrized.agda b/src/Categories/Object/NaturalNumbers/Properties/Parametrized.agda index 517fc7750..c7ffa1cef 100644 --- a/src/Categories/Object/NaturalNumbers/Properties/Parametrized.agda +++ b/src/Categories/Object/NaturalNumbers/Properties/Parametrized.agda @@ -56,7 +56,7 @@ NNO×CCC⇒PNNO nno = record commute₂' {A} {X} {f} {g} = begin g ∘ (eval′ ∘ (universal (λg (f ∘ π₂)) (λg (g ∘ eval′)) ⁂ id)) ∘ swap ≈⟨ pullˡ (pullˡ (⟺ β′)) ⟩ ((eval′ ∘ (λg (g ∘ eval′) ⁂ id)) ∘ (universal (λg (f ∘ π₂)) (λg (g ∘ eval′)) ⁂ id)) ∘ swap ≈⟨ (pullʳ ⁂∘⁂) ⟩∘⟨refl ⟩ - (eval′ ∘ (λg (g ∘ eval′) ∘ universal (λg (f ∘ π₂)) (λg (g ∘ eval′)) ⁂ id ∘ id)) ∘ swap ≈⟨ (refl⟩∘⟨ (⁂-cong₂ s-commute refl)) ⟩∘⟨refl ⟩ + (eval′ ∘ (λg (g ∘ eval′) ∘ universal (λg (f ∘ π₂)) (λg (g ∘ eval′)) ⁂ id ∘ id)) ∘ swap ≈⟨ (refl⟩∘⟨ first-cong s-commute) ⟩∘⟨refl ⟩ (eval′ ∘ (universal (λg (f ∘ π₂)) (λg (g ∘ eval′)) ∘ s ⁂ id ∘ id)) ∘ swap ≈⟨ (refl⟩∘⟨ (⟺ ⁂∘⁂)) ⟩∘⟨refl ⟩ (eval′ ∘ (universal (λg (f ∘ π₂)) (λg (g ∘ eval′)) ⁂ id) ∘ (s ⁂ id)) ∘ swap ≈⟨ pullʳ (pullʳ (⟺ swap∘⁂)) ⟩ eval′ ∘ (universal (λg (f ∘ π₂)) (λg (g ∘ eval′)) ⁂ id) ∘ swap ∘ (id ⁂ s) ≈⟨ sym-assoc ○ sym-assoc ⟩ @@ -72,7 +72,7 @@ NNO×CCC⇒PNNO nno = record where z-commutes : λg (u ∘ swap) ∘ z ≈ λg (f ∘ π₂) z-commutes = λ-unique′ (begin - eval′ ∘ (λg (u ∘ swap) ∘ z ⁂ id) ≈˘⟨ refl⟩∘⟨ (⁂∘⁂ ○ ⁂-cong₂ refl identity²) ⟩ + eval′ ∘ (λg (u ∘ swap) ∘ z ⁂ id) ≈˘⟨ refl⟩∘⟨ (⁂∘⁂ ○ second-cong identity²) ⟩ eval′ ∘ (λg (u ∘ swap) ⁂ id) ∘ (z ⁂ id) ≈⟨ extendʳ β′ ⟩ u ∘ swap ∘ (z ⁂ id) ≈⟨ refl⟩∘⟨ swap∘⁂ ⟩ u ∘ (id ⁂ z) ∘ swap ≈⟨ refl⟩∘⟨ (bp-unique′ π₁-commutes π₂-commutes) ⟩