open import Level
open import Categories.Category.Core
open import Categories.Functor.Coalgebra
open import Categories.Monad.Commutative
open import Monad.Instance.Delay
open import Categories.Category.Distributive
open import Monad.Helper
import Categories.Morphism as M
import Categories.Morphism.Reasoning as MR
import Categories.Morphism.Properties as MP
module Monad.Instance.Delay.Commutative {o ℓ e} {C : Category o ℓ e} (distributive : Distributive C) (D : DelayM (Distributive.cocartesian distributive)) where
open Category C
open import Category.Distributive.Helper distributive
open Bundles
open HomReasoning
open Equiv
open MR C
open MP C
open M C
open DelayM D
open D-Kleisli
open D-Monad
open Later∘Extend
open import Monad.Instance.Delay.Strong distributive D public
open D-Strong
open import Monad.Instance.Delay.Guarded cocartesian D
module σ-mod where
open τ-mod
σ : ∀ {X Y} → D₀ X × Y ⇒ D₀ (X × Y)
σ = D₁ swap ∘ τ ∘ swap
abstract
σ-law : ∀ {X} {Y} → out ∘ σ {X} {Y} ≈ (id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id)
σ-law = begin
out ∘ σ ≈⟨ pullˡ (D₁-commutes swap) ⟩
((swap +₁ D₁ swap) ∘ out) ∘ τ ∘ swap ≈⟨ pullˡ (pullʳ τ-commutes) ⟩
((swap +₁ D₁ swap) ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) ∘ swap ≈⟨ pullʳ (pullʳ (pullʳ (sym swap∘⁂))) ⟩
(swap +₁ D₁ swap) ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ swap ∘ (out ⁂ id) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ pullˡ distributeˡ⁻¹∘swap ⟩
(swap +₁ D₁ swap) ∘ (id +₁ τ) ∘ ((swap +₁ swap) ∘ distributeʳ⁻¹) ∘ (out ⁂ id) ≈⟨ pullˡ +₁∘+₁ ⟩
(swap ∘ id +₁ D₁ swap ∘ τ) ∘ ((swap +₁ swap) ∘ distributeʳ⁻¹) ∘ (out ⁂ id) ≈⟨ pullˡ (pullˡ +₁∘+₁) ⟩
(((swap ∘ id) ∘ swap +₁ (D₁ swap ∘ τ) ∘ swap) ∘ distributeʳ⁻¹) ∘ (out ⁂ id) ≈⟨ ((+₁-cong₂ (identityʳ ⟩∘⟨refl ○ swap∘swap) assoc) ⟩∘⟨refl) ⟩∘⟨refl ⟩
((id +₁ D₁ swap ∘ τ ∘ swap) ∘ distributeʳ⁻¹) ∘ (out ⁂ id) ≈⟨ assoc ⟩
(id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id) ∎
σ-helper : ∀ {X Y} → (σ {X} {Y}) ∘ (out⁻¹ ⁂ id) ≈ out⁻¹ ∘ (id +₁ σ) ∘ distributeʳ⁻¹
σ-helper = begin
σ ∘ (out⁻¹ ⁂ id) ≈⟨ introˡ out⁻¹∘out ⟩
(out⁻¹ ∘ out) ∘ σ ∘ (out⁻¹ ⁂ id) ≈⟨ pullʳ (pullˡ σ-law) ⟩
out⁻¹ ∘ ((id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id)) ∘ (out⁻¹ ⁂ id) ≈⟨ refl⟩∘⟨ (pullʳ (cancelʳ (⁂∘⁂ ○ ⁂-cong₂ out∘out⁻¹ identity² ○ ⟨⟩-unique id-comm id-comm))) ⟩
out⁻¹ ∘ (id +₁ σ) ∘ distributeʳ⁻¹ ∎
σ-now : ∀ {X} {Y} → σ {X} {Y} ∘ (now ⁂ id) ≈ now
σ-now = begin
(D₁ swap ∘ τ ∘ swap) ∘ (now ⁂ id) ≈⟨ pullʳ (pullʳ swap∘⁂) ⟩
D₁ swap ∘ τ ∘ (id ⁂ now) ∘ swap ≈⟨ refl⟩∘⟨ pullˡ τ-now ⟩
D₁ swap ∘ now ∘ swap ≈⟨ extendʳ (sym (D.η.commute swap)) ⟩
now ∘ swap ∘ swap ≈⟨ elimʳ swap∘swap ⟩
now ∎
later∘σ : ∀ {X} {Y} → σ {X} {Y} ∘ (later ⁂ id) ≈ later ∘ σ
later∘σ = begin
(D₁ swap ∘ τ ∘ swap) ∘ (later ⁂ id) ≈⟨ pullʳ (pullʳ swap∘⁂) ⟩
D₁ swap ∘ τ ∘ (id ⁂ later) ∘ swap ≈⟨ refl⟩∘⟨ (extendʳ τ-later) ⟩
D₁ swap ∘ later ∘ τ ∘ swap ≈⟨ extendʳ (sym (later-extend-comm (now ∘ swap))) ⟩
later ∘ D₁ swap ∘ τ ∘ swap ∎
σ-unique : ∀ {X Y} → (s : D₀ X × Y ⇒ D₀ (X × Y)) → (out ∘ s ≈ (id +₁ s) ∘ distributeʳ⁻¹ ∘ (out ⁂ id)) → s ≈ σ
σ-unique s s-commutes = begin
s ≈˘⟨ elimʳ swap∘swap ⟩
s ∘ swap ∘ swap ≈˘⟨ cancelˡ ((sym D.F.homomorphism) ○ D.F.F-resp-≈ swap∘swap ○ D.F.identity) ⟩
D₁ swap ∘ D₁ swap ∘ s ∘ swap ∘ swap ≈⟨ refl⟩∘⟨ (sym-assoc ○ pullˡ (assoc ○ sym (τ-unique (D₁ swap ∘ s ∘ swap) helper))) ⟩
D₁ swap ∘ τ ∘ swap ∎
where
helper : out ∘ D₁ swap ∘ s ∘ swap ≈ (id +₁ D₁ swap ∘ s ∘ swap) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
helper = begin
out ∘ D₁ swap ∘ s ∘ swap ≈⟨ extendʳ (D₁-commutes swap) ⟩
(swap +₁ D₁ swap) ∘ out ∘ s ∘ swap ≈⟨ refl⟩∘⟨ (extendʳ s-commutes) ⟩
(swap +₁ D₁ swap) ∘ (id +₁ s) ∘ (distributeʳ⁻¹ ∘ (out ⁂ id)) ∘ swap ≈⟨ pullˡ (+₁∘+₁ ○ +₁-cong₂ identityʳ refl) ⟩
(swap +₁ D₁ swap ∘ s) ∘ (distributeʳ⁻¹ ∘ (out ⁂ id)) ∘ swap ≈⟨ refl⟩∘⟨ (pullʳ (sym swap∘⁂)) ⟩
(swap +₁ D₁ swap ∘ s) ∘ distributeʳ⁻¹ ∘ swap ∘ (id ⁂ out) ≈⟨ refl⟩∘⟨ (extendʳ distributeʳ⁻¹∘swap) ⟩
(swap +₁ D₁ swap ∘ s) ∘ (swap +₁ swap) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ pullˡ (+₁∘+₁ ○ +₁-cong₂ swap∘swap assoc) ⟩
(id +₁ D₁ swap ∘ s ∘ swap) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∎
σ-natural : ∀ {U V W X : Obj} (f : U ⇒ V) (g : W ⇒ X) → σ ∘ (extend (now ∘ f) ⁂ g) ≈ extend (now ∘ (f ⁂ g)) ∘ σ
σ-natural f g = begin
σ ∘ (D₁ f ⁂ g) ≈⟨ pullʳ (pullʳ swap∘⁂) ⟩
D₁ swap ∘ τ ∘ (g ⁂ extend (now ∘ f)) ∘ swap ≈⟨ refl⟩∘⟨ (pullˡ (τ-natural g f)) ⟩
D₁ swap ∘ (D₁ (g ⁂ f) ∘ τ) ∘ swap ≈⟨ pullˡ (pullˡ (sym D.F.homomorphism)) ⟩
(D₁ (swap ∘ (g ⁂ f)) ∘ τ) ∘ swap ≈⟨ ((D.F.F-resp-≈ swap∘⁂) ⟩∘⟨refl) ⟩∘⟨refl ⟩
(D₁ ((f ⁂ g) ∘ swap) ∘ τ) ∘ swap ≈⟨ pushˡ D.F.homomorphism ⟩∘⟨refl ⟩
(D₁ (f ⁂ g) ∘ D₁ swap ∘ τ) ∘ swap ≈⟨ assoc²βε ⟩
D₁ (f ⁂ g) ∘ σ ∎
open τ-mod
open σ-mod
στ-comm : ∀ {X} {Y} → extend σ ∘ τ {D₀ X} {Y} ≈ out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , later ∘ extend σ ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out)
στ-comm = out-mono (extend σ ∘ τ) (out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , later ∘ extend σ ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out)) (begin
out ∘ extend σ ∘ τ ≈⟨ pullˡ (extend-commutes σ) ⟩
([ out ∘ σ , i₂ ∘ extend σ ] ∘ out) ∘ τ ≈⟨ pullʳ τ-commutes ⟩
[ out ∘ σ , i₂ ∘ extend σ ] ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ pullˡ []∘+₁ ⟩
[ (out ∘ σ) ∘ id , (i₂ ∘ extend σ) ∘ τ ] ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ ([]-cong₂ (identityʳ ○ σ-law) assoc) ⟩∘⟨refl ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id) , i₂ ∘ extend σ ∘ τ ] ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ⁂-cong₂ (sym out⁻¹∘out) refl ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id) , i₂ ∘ extend σ ∘ τ ] ∘ distributeˡ⁻¹ ∘ (out⁻¹ ∘ out ⁂ out) ≈⟨ sym (refl⟩∘⟨ refl⟩∘⟨ (⁂∘⁂ ○ ⁂-cong₂ refl (elimˡ ([]-unique id-comm-sym id-comm-sym)))) ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id) , i₂ ∘ extend σ ∘ τ ] ∘ distributeˡ⁻¹ ∘ (out⁻¹ ⁂ (id +₁ id)) ∘ (out ⁂ out) ≈⟨ refl⟩∘⟨ pullˡ (sym (distributeˡ⁻¹-natural out⁻¹ id id)) ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id) , i₂ ∘ extend σ ∘ τ ] ∘ (((out⁻¹ ⁂ id) +₁ (out⁻¹ ⁂ id)) ∘ distributeˡ⁻¹) ∘ (out ⁂ out) ≈⟨ pullˡ (pullˡ []∘+₁) ⟩
([ ((id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id)) ∘ (out⁻¹ ⁂ id) , (i₂ ∘ extend σ ∘ τ) ∘ (out⁻¹ ⁂ id) ] ∘ distributeˡ⁻¹) ∘ (out ⁂ out) ≈⟨ assoc ○ ([]-cong₂ (pullʳ (cancelʳ (⁂∘⁂ ○ ⁂-cong₂ out∘out⁻¹ identity² ○ ⟨⟩-unique id-comm id-comm))) (refl⟩∘⟨ (⁂-cong₂ refl (sym D.F.identity)) ○ (pullʳ (pullʳ (τ-natural out⁻¹ id))))) ⟩∘⟨refl ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ , i₂ ∘ extend σ ∘ D₁ (out⁻¹ ⁂ id) ∘ τ ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ (pullˡ (sym DK.assoc)) ○ refl⟩∘⟨ ((extend-≈ (pullˡ DK.identityʳ)) ⟩∘⟨refl))) ⟩∘⟨refl ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ , i₂ ∘ extend (σ ∘ (out⁻¹ ⁂ id)) ∘ τ ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ((extend-≈ σ-helper) ⟩∘⟨refl))) ⟩∘⟨refl ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ , i₂ ∘ extend (out⁻¹ ∘ (id +₁ σ) ∘ distributeʳ⁻¹) ∘ τ ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈˘⟨ ([]-cong₂ refl (refl⟩∘⟨ ((sym DK.assoc ○ extend-≈ (pullˡ DK.identityʳ) ○ extend-≈ assoc) ⟩∘⟨refl))) ⟩∘⟨refl ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ , i₂ ∘ (extend (out⁻¹ ∘ (id +₁ σ)) ∘ D₁ distributeʳ⁻¹) ∘ τ ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ pullʳ helper₁)) ⟩∘⟨refl ⟩
[ (id +₁ σ) ∘ distributeʳ⁻¹ , i₂ ∘ extend (out⁻¹ ∘ (id +₁ σ)) ∘ [ D₁ i₁ ∘ τ , D₁ i₂ ∘ τ ] ∘ distributeʳ⁻¹ ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈˘⟨ pullˡ ([]∘+₁ ○ []-cong₂ refl assoc²βε) ⟩
[ (id +₁ σ) , i₂ ∘ extend (out⁻¹ ∘ (id +₁ σ)) ∘ [ D₁ i₁ ∘ τ , D₁ i₂ ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ∘[])) ⟩∘⟨refl ⟩
[ (id +₁ σ) , i₂ ∘ [ extend (out⁻¹ ∘ (id +₁ σ)) ∘ D₁ i₁ ∘ τ , extend (out⁻¹ ∘ (id +₁ σ)) ∘ D₁ i₂ ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ (pullˡ ((sym DK.assoc) ○ extend-≈ (pullˡ DK.identityʳ))) (pullˡ ((sym DK.assoc) ○ extend-≈ (pullˡ DK.identityʳ)))))) ⟩∘⟨refl ⟩
[ (id +₁ σ) , i₂ ∘ [ extend ((out⁻¹ ∘ (id +₁ σ)) ∘ i₁) ∘ τ , extend ((out⁻¹ ∘ (id +₁ σ)) ∘ i₂) ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ ((extend-≈ (pullʳ +₁∘i₁)) ⟩∘⟨refl) ((extend-≈ (pullʳ +₁∘i₂)) ⟩∘⟨refl)))) ⟩∘⟨refl ⟩
[ (id +₁ σ) , i₂ ∘ [ extend (out⁻¹ ∘ i₁ ∘ id) ∘ τ , extend (out⁻¹ ∘ i₂ ∘ σ) ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ (elimˡ ((extend-≈ (refl⟩∘⟨ identityʳ)) ○ DK.identityˡ)) ((extend-≈ sym-assoc) ⟩∘⟨refl)))) ⟩∘⟨refl ⟩
[ (id +₁ σ) , i₂ ∘ [ τ , extend (later ∘ σ) ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ refl ((sym (later∘extend σ)) ⟩∘⟨refl ○ assoc)))) ⟩∘⟨refl ⟩
[ id +₁ σ , i₂ ∘ [ τ , later ∘ extend σ ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈˘⟨ cancelˡ out∘out⁻¹ ⟩
out ∘ out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , later ∘ extend σ ∘ τ ] ] ∘ (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ∎)
where
helper₁ : (D₁ distributeʳ⁻¹) ∘ τ ≈ [ D₁ i₁ ∘ τ , D₁ i₂ ∘ τ ] ∘ distributeʳ⁻¹
helper₁ = Iso⇒Epi (IsIso.iso isIsoʳ) ((D₁ distributeʳ⁻¹) ∘ τ) ([ D₁ i₁ ∘ τ , D₁ i₂ ∘ τ ] ∘ distributeʳ⁻¹) (begin
((D₁ distributeʳ⁻¹) ∘ τ) ∘ distributeʳ ≈⟨ ∘[] ○ []-cong₂ (refl⟩∘⟨ (⁂-cong₂ refl (sym D.F.identity))) (refl⟩∘⟨ (⁂-cong₂ refl (sym D.F.identity))) ⟩
[ ((D₁ distributeʳ⁻¹) ∘ τ) ∘ (i₁ ⁂ D₁ id) , ((D₁ distributeʳ⁻¹) ∘ τ) ∘ (i₂ ⁂ D₁ id) ] ≈⟨ []-cong₂ (pullʳ (τ-natural i₁ id)) (pullʳ (τ-natural i₂ id)) ⟩
[ (D₁ distributeʳ⁻¹) ∘ D₁ (i₁ ⁂ id) ∘ τ , (D₁ distributeʳ⁻¹) ∘ D₁ (i₂ ⁂ id) ∘ τ ] ≈⟨ []-cong₂ (pullˡ (sym D.F.homomorphism)) (pullˡ (sym D.F.homomorphism)) ⟩
[ D₁ (distributeʳ⁻¹ ∘ (i₁ ⁂ id)) ∘ τ , D₁ (distributeʳ⁻¹ ∘ (i₂ ⁂ id)) ∘ τ ] ≈⟨ []-cong₂ (D.F.F-resp-≈ distributeʳ⁻¹-i₁ ⟩∘⟨refl) ((D.F.F-resp-≈ distributeʳ⁻¹-i₂) ⟩∘⟨refl) ⟩
[ D₁ i₁ ∘ τ , D₁ i₂ ∘ τ ] ≈˘⟨ cancelʳ (IsIso.isoˡ isIsoʳ) ⟩
([ D₁ i₁ ∘ τ , D₁ i₂ ∘ τ ] ∘ distributeʳ⁻¹) ∘ distributeʳ ∎)
commutativeMonad : Commutative braided strongMonad
commutativeMonad = record { commutes = λ {X} {Y} → pullˡ (Kleisli⇒Monad⇒Kleisli kleisli _) ○ commutes' ○ pushˡ (sym (Kleisli⇒Monad⇒Kleisli kleisli _)) }
where
commutes' : ∀ {X Y} → extend σ ∘ τ ≈ extend τ ∘ σ
commutes' {X} {Y} = guarded-unique g (extend σ ∘ τ) (extend τ ∘ σ) guarded (fixpoint-eq στ-comm) (fixpoint-eq fixpoint₂)
where
w = (distributeʳ⁻¹ +₁ distributeʳ⁻¹) ∘ distributeˡ⁻¹ ∘ (out ⁂ out)
g = out⁻¹ ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w
guarded : IsGuarded g
guarded = record
{ guard = [ id +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w
; guard-eq = begin
(i₁ +₁ id) ∘ [ id +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈⟨ pullˡ (∘[] ○ []-cong₂ (+₁∘+₁ ○ +₁-cong₂ identityʳ identityˡ) (pullˡ (+₁∘i₂ ○ identityʳ))) ⟩
[ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈˘⟨ cancelˡ out∘out⁻¹ ⟩
out ∘ out⁻¹ ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ∎
}
fixpoint₂ : extend τ ∘ σ ≈ out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , later ∘ extend τ ∘ σ ] ] ∘ w
fixpoint₂ = out-mono (extend τ ∘ σ) (out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , later ∘ extend τ ∘ σ ] ] ∘ w) (begin
out ∘ extend τ ∘ σ ≈⟨ pullˡ (extend-commutes τ) ⟩
([ out ∘ τ , i₂ ∘ extend τ ] ∘ out) ∘ σ ≈⟨ pullʳ σ-law ⟩
[ out ∘ τ , i₂ ∘ extend τ ] ∘ (id +₁ σ) ∘ distributeʳ⁻¹ ∘ (out ⁂ id) ≈⟨ pullˡ ([]∘+₁ ○ []-cong₂ (identityʳ ○ τ-commutes) assoc) ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ extend τ ∘ σ ] ∘ distributeʳ⁻¹ ∘ (out ⁂ id) ≈˘⟨ refl⟩∘⟨ (refl⟩∘⟨ (⁂∘⁂ ○ ⁂-cong₂ (elimˡ ([]-unique id-comm-sym id-comm-sym)) out⁻¹∘out)) ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ extend τ ∘ σ ] ∘ distributeʳ⁻¹ ∘ ((id +₁ id) ⁂ out⁻¹) ∘ (out ⁂ out) ≈⟨ refl⟩∘⟨ (pullˡ (sym (distributeʳ⁻¹-natural out⁻¹ id id))) ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ extend τ ∘ σ ] ∘ (((id ⁂ out⁻¹) +₁ (id ⁂ out⁻¹)) ∘ distributeʳ⁻¹) ∘ (out ⁂ out) ≈⟨ pullˡ (pullˡ ([]∘+₁ ○ []-cong₂ (pullʳ (cancelʳ (⁂∘⁂ ○ ⁂-cong₂ identity² out∘out⁻¹ ○ ⟨⟩-unique id-comm id-comm))) (refl⟩∘⟨ (⁂-cong₂ (sym D.F.identity) refl)))) ○ assoc ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ , (i₂ ∘ extend τ ∘ σ) ∘ (D₁ id ⁂ out⁻¹) ] ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (pullʳ (pullʳ (σ-natural id out⁻¹)))) ⟩∘⟨refl ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ , i₂ ∘ extend τ ∘ D₁ (id ⁂ out⁻¹) ∘ σ ] ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ (pullˡ ((sym DK.assoc) ○ extend-≈ (pullˡ DK.identityʳ))))) ⟩∘⟨refl ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ , i₂ ∘ extend (τ ∘ (id ⁂ out⁻¹)) ∘ σ ] ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ((extend-≈ τ-out⁻¹) ⟩∘⟨refl))) ⟩∘⟨refl ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ , i₂ ∘ extend (out⁻¹ ∘ (id +₁ τ) ∘ distributeˡ⁻¹) ∘ σ ] ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈˘⟨ ([]-cong₂ refl (refl⟩∘⟨ pullˡ ((sym DK.assoc) ○ (extend-≈ (pullˡ DK.identityʳ) ○ extend-≈ assoc)))) ⟩∘⟨refl ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ , i₂ ∘ extend (out⁻¹ ∘ (id +₁ τ)) ∘ D₁ distributeˡ⁻¹ ∘ σ ] ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl ((refl⟩∘⟨ (refl⟩∘⟨ helper₂)) ○ sym assoc²βε)) ⟩∘⟨refl ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ , (i₂ ∘ extend (out⁻¹ ∘ (id +₁ τ)) ∘ [ D₁ i₁ ∘ σ , D₁ i₂ ∘ σ ]) ∘ distributeˡ⁻¹ ] ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈˘⟨ []∘+₁ ⟩∘⟨refl ⟩
([ (id +₁ τ) , i₂ ∘ extend (out⁻¹ ∘ (id +₁ τ)) ∘ [ D₁ i₁ ∘ σ , D₁ i₂ ∘ σ ] ] ∘ (distributeˡ⁻¹ +₁ distributeˡ⁻¹)) ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ assoc ○ ([]-cong₂ refl (refl⟩∘⟨ ∘[])) ⟩∘⟨refl ⟩
[ (id +₁ τ) , i₂ ∘ [ extend (out⁻¹ ∘ (id +₁ τ)) ∘ D₁ i₁ ∘ σ , extend (out⁻¹ ∘ (id +₁ τ)) ∘ D₁ i₂ ∘ σ ] ] ∘ (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ (pullˡ (sym DK.assoc ○ extend-≈ (pullˡ DK.identityʳ))) (pullˡ (sym DK.assoc ○ extend-≈ (pullˡ DK.identityʳ)))))) ⟩∘⟨refl ⟩
[ (id +₁ τ) , i₂ ∘ [ extend ((out⁻¹ ∘ (id +₁ τ)) ∘ i₁) ∘ σ , extend ((out⁻¹ ∘ (id +₁ τ)) ∘ i₂) ∘ σ ] ] ∘ (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ []-cong₂ refl (refl⟩∘⟨ []-cong₂ (extend-≈ (pullʳ inject₁) ⟩∘⟨refl) (extend-≈ (pullʳ inject₂) ⟩∘⟨refl)) ⟩∘⟨refl ⟩
[ (id +₁ τ) , i₂ ∘ [ extend (out⁻¹ ∘ i₁ ∘ id) ∘ σ , extend (out⁻¹ ∘ i₂ ∘ τ) ∘ σ ] ] ∘ (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ []-cong₂ refl (refl⟩∘⟨ []-cong₂ (elimˡ (extend-≈ (refl⟩∘⟨ identityʳ) ○ DK.identityˡ)) (extend-≈ sym-assoc ⟩∘⟨refl ○ sym (pullˡ (later∘extend τ)))) ⟩∘⟨refl ⟩
[ (id +₁ τ) , i₂ ∘ [ σ , later ∘ extend τ ∘ σ ] ] ∘ (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ≈⟨ helper₃ ⟩
[ id +₁ σ , i₂ ∘ [ τ , later ∘ extend τ ∘ σ ] ] ∘ w ≈˘⟨ cancelˡ out∘out⁻¹ ⟩
out ∘ out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , later ∘ extend τ ∘ σ ] ] ∘ w ∎)
where
helper₂ : (D₁ distributeˡ⁻¹) ∘ σ ≈ [ D₁ i₁ ∘ σ , D₁ i₂ ∘ σ ] ∘ distributeˡ⁻¹
helper₂ = Iso⇒Epi (IsIso.iso isIsoˡ) ((D₁ distributeˡ⁻¹) ∘ σ) ([ D₁ i₁ ∘ σ , D₁ i₂ ∘ σ ] ∘ distributeˡ⁻¹) (begin
((D₁ distributeˡ⁻¹) ∘ σ) ∘ distributeˡ ≈⟨ ∘[] ○ []-cong₂ (refl⟩∘⟨ ⁂-cong₂ (sym D.F.identity) refl) (refl⟩∘⟨ ⁂-cong₂ (sym D.F.identity) refl) ⟩
[ ((D₁ distributeˡ⁻¹) ∘ σ) ∘ (D₁ id ⁂ i₁) , ((D₁ distributeˡ⁻¹) ∘ σ) ∘ (D₁ id ⁂ i₂) ] ≈⟨ []-cong₂ (pullʳ (σ-natural id i₁)) (pullʳ (σ-natural id i₂)) ⟩
[ (D₁ distributeˡ⁻¹) ∘ D₁ (id ⁂ i₁) ∘ σ , (D₁ distributeˡ⁻¹) ∘ D₁ (id ⁂ i₂) ∘ σ ] ≈⟨ []-cong₂ (pullˡ (sym D.F.homomorphism)) (pullˡ (sym D.F.homomorphism)) ⟩
[ D₁ (distributeˡ⁻¹ ∘ (id ⁂ i₁)) ∘ σ , D₁ (distributeˡ⁻¹ ∘ (id ⁂ i₂)) ∘ σ ] ≈⟨ []-cong₂ (D.F.F-resp-≈ distributeˡ⁻¹-i₁ ⟩∘⟨refl) (D.F.F-resp-≈ distributeˡ⁻¹-i₂ ⟩∘⟨refl) ⟩
[ D₁ i₁ ∘ σ , D₁ i₂ ∘ σ ] ≈˘⟨ cancelʳ (IsIso.isoˡ isIsoˡ) ⟩
([ D₁ i₁ ∘ σ , D₁ i₂ ∘ σ ] ∘ distributeˡ⁻¹) ∘ distributeˡ ∎)
helper₃ : [ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ (out {X} ⁂ out {Y}) ≈ [ id +₁ σ , i₂ ∘ [ τ , later ∘ extend τ ∘ σ ] ] ∘ w
helper₃ = begin
[ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ (out {X} ⁂ out {Y}) ≈⟨ refl⟩∘⟨ helper ⟩
[ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ [ [ i₁ ∘ i₁ , i₂ ∘ i₁ ] , [ (i₁ ∘ i₂) , (i₂ ∘ i₂) ] ] ∘ w ≈⟨ pullˡ ∘[] ⟩
[ [ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ [ i₁ ∘ i₁ , i₂ ∘ i₁ ]
, [ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ [ (i₁ ∘ i₂) , (i₂ ∘ i₂) ] ] ∘ w ≈⟨ ([]-cong₂ ∘[] ∘[]) ⟩∘⟨refl ⟩
[ [ [ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ i₁ ∘ i₁ , [ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ i₂ ∘ i₁ ]
, [ [ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ (i₁ ∘ i₂)
, [ id +₁ τ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ] ∘ (i₂ ∘ i₂) ] ] ∘ w ≈⟨ ([]-cong₂ ([]-cong₂ (pullˡ inject₁) (pullˡ inject₂ ○ assoc)) ([]-cong₂ (pullˡ inject₁) (pullˡ inject₂ ○ assoc))) ⟩∘⟨refl ⟩
[ [ (id +₁ τ) ∘ i₁ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ∘ i₁ ] , [ (id +₁ τ) ∘ i₂ , i₂ ∘ [ D₁ swap ∘ τ ∘ swap , later ∘ extend τ ∘ σ ] ∘ i₂ ] ] ∘ w ≈⟨ ([]-cong₂ ([]-cong₂ (+₁∘i₁ ○ identityʳ) (refl⟩∘⟨ inject₁)) ([]-cong₂ +₁∘i₂ (refl⟩∘⟨ inject₂))) ⟩∘⟨refl ⟩
[ [ i₁ , i₂ ∘ σ ] , [ i₂ ∘ τ , i₂ ∘ later ∘ extend τ ∘ σ ] ] ∘ w ≈˘⟨ ([]-cong₂ ([]-cong₂ identityʳ refl) ∘[]) ⟩∘⟨refl ⟩
[ id +₁ σ , i₂ ∘ [ τ , later ∘ extend τ ∘ σ ] ] ∘ w ∎
where
helper : (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ (out {X} ⁂ out {Y}) ≈ [ [ i₁ ∘ i₁ , i₂ ∘ i₁ ] , [ (i₁ ∘ i₂) , (i₂ ∘ i₂) ] ] ∘ w
helper = sym (begin
[ [ i₁ ∘ i₁ , i₂ ∘ i₁ ] , [ (i₁ ∘ i₂) , (i₂ ∘ i₂) ] ] ∘ w ≈⟨ pullˡ ([]∘+₁ ○ []-cong₂ ((+₁-cong₂ (sym distributeˡ⁻¹-i₁) (sym distributeˡ⁻¹-i₁)) ⟩∘⟨refl) ((+₁-cong₂ (sym distributeˡ⁻¹-i₂) (sym distributeˡ⁻¹-i₂)) ⟩∘⟨refl)) ⟩
[ (distributeˡ⁻¹ ∘ (id ⁂ i₁) +₁ distributeˡ⁻¹ ∘ (id ⁂ i₁)) ∘ distributeʳ⁻¹
, (distributeˡ⁻¹ ∘ (id ⁂ i₂) +₁ distributeˡ⁻¹ ∘ (id ⁂ i₂)) ∘ distributeʳ⁻¹ ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈˘⟨ ([]-cong₂ (pullˡ +₁∘+₁) (pullˡ +₁∘+₁)) ⟩∘⟨refl ⟩
[ (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ ((id ⁂ i₁) +₁ (id ⁂ i₁)) ∘ distributeʳ⁻¹
, (distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ ((id ⁂ i₂) +₁ (id ⁂ i₂)) ∘ distributeʳ⁻¹ ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈˘⟨ pullˡ ∘[] ⟩
(distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ [ ((id ⁂ i₁) +₁ (id ⁂ i₁)) ∘ distributeʳ⁻¹ , ((id ⁂ i₂) +₁ (id ⁂ i₂)) ∘ distributeʳ⁻¹ ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ refl⟩∘⟨ []-cong₂ (distributeʳ⁻¹-natural i₁ id id) (distributeʳ⁻¹-natural i₂ id id) ⟩∘⟨refl ⟩
(distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ [ distributeʳ⁻¹ ∘ ((id +₁ id) ⁂ i₁) , distributeʳ⁻¹ ∘ ((id +₁ id) ⁂ i₂) ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈˘⟨ refl⟩∘⟨ pullˡ ∘[] ⟩
(distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ [ ((id +₁ id) ⁂ i₁) , ((id +₁ id) ⁂ i₂) ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ([]-cong₂ (⁂-cong₂ ([]-unique id-comm-sym id-comm-sym) refl) (⁂-cong₂ ([]-unique id-comm-sym id-comm-sym) refl)) ⟩∘⟨refl ⟩
(distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ [ (id ⁂ i₁) , (id ⁂ i₂) ] ∘ distributeˡ⁻¹ ∘ (out ⁂ out) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ cancelˡ (IsIso.isoʳ isIsoˡ) ⟩
(distributeˡ⁻¹ +₁ distributeˡ⁻¹) ∘ distributeʳ⁻¹ ∘ (out ⁂ out) ∎)
fixpoint-eq : ∀ {f : D₀ X × D₀ Y ⇒ D₀ (X × Y)} → f ≈ out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , later ∘ f ] ] ∘ w → f ≈ extend [ now , f ] ∘ g
fixpoint-eq {f} fix = begin
f ≈⟨ fix ⟩
out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , later ∘ f ] ] ∘ w ≈˘⟨ refl⟩∘⟨ []-cong₂ refl (refl⟩∘⟨ ([]-cong₂ refl (pullʳ inject₂))) ⟩∘⟨refl ⟩
out⁻¹ ∘ [ id +₁ σ , i₂ ∘ [ τ , (later ∘ [ now , f ]) ∘ i₂ ] ] ∘ w ≈˘⟨ refl⟩∘⟨ []-cong₂ refl (sym ∘[] ○ refl⟩∘⟨ []-cong₂ (elimˡ (extend-≈ inject₁ ○ DK.identityˡ)) (pullˡ DK.identityʳ)) ⟩∘⟨refl ⟩
out⁻¹ ∘ [ id +₁ σ , [ i₂ ∘ extend ([ now , f ] ∘ i₁) ∘ τ , i₂ ∘ extend (later ∘ [ now , f ]) ∘ now ∘ i₂ ] ] ∘ w ≈˘⟨ refl⟩∘⟨ (([]-cong₂ ([]-cong₂ (sym identityʳ) (∘-resp-≈ʳ (elimˡ (extend-≈ inject₁ ○ DK.identityˡ)))) ([]-cong₂ (pullʳ (pullˡ (DK.sym-assoc ○ extend-≈ (pullˡ DK.identityʳ)))) (pullʳ (pullˡ (extend∘later [ now , f ]))))) ⟩∘⟨refl) ⟩
out⁻¹ ∘ [ [ i₁ , i₂ ∘ extend ([ now , f ] ∘ i₁) ∘ σ ] , [ (i₂ ∘ extend [ now , f ]) ∘ D₁ i₁ ∘ τ , (i₂ ∘ extend [ now , f ]) ∘ later ∘ now ∘ i₂ ] ] ∘ w ≈˘⟨ refl⟩∘⟨ []-cong₂ ([]-cong₂ inject₁ (pullʳ (pullˡ ((sym DK.assoc) ○ extend-≈ (pullˡ DK.identityʳ))))) ∘[] ⟩∘⟨refl ⟩
out⁻¹ ∘ [ [ [ i₁ , out ∘ f ] ∘ i₁ , (i₂ ∘ extend [ now , f ]) ∘ D₁ i₁ ∘ σ ] , (i₂ ∘ extend [ now , f ]) ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈˘⟨ refl⟩∘⟨ (([]-cong₂ []∘+₁ (pullˡ inject₂)) ⟩∘⟨refl) ⟩
out⁻¹ ∘ [ [ [ i₁ , out ∘ f ] , i₂ ∘ extend [ now , f ] ] ∘ (i₁ +₁ D₁ i₁ ∘ σ) , [ [ i₁ , out ∘ f ] , i₂ ∘ extend [ now , f ] ] ∘ i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈˘⟨ refl⟩∘⟨ (pullˡ ∘[]) ⟩
out⁻¹ ∘ [ [ i₁ , out ∘ f ] , i₂ ∘ extend [ now , f ] ] ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈⟨ out-mono (out⁻¹ ∘ [ [ i₁ , out ∘ f ] , i₂ ∘ extend [ now , f ] ] ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w) (extend [ now , f ] ∘ out⁻¹ ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w) helper ⟩
extend [ now , f ] ∘ out⁻¹ ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ∎
where
helper = begin
out ∘ out⁻¹ ∘ [ [ i₁ , out ∘ f ] , i₂ ∘ extend [ now , f ] ] ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈⟨ cancelˡ out∘out⁻¹ ⟩
[ [ i₁ , out ∘ f ] , i₂ ∘ extend [ now , f ] ] ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈˘⟨ ([]-cong₂ (∘[] ○ []-cong₂ unitlaw refl) refl) ⟩∘⟨refl ⟩
[ out ∘ [ now , f ] , i₂ ∘ extend [ now , f ] ] ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈˘⟨ pullʳ (cancelˡ out∘out⁻¹) ⟩
([ out ∘ [ now , f ] , i₂ ∘ extend [ now , f ] ] ∘ out) ∘ out⁻¹ ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ≈˘⟨ pullˡ (extend-commutes [ now , f ]) ⟩
out ∘ extend [ now , f ] ∘ out⁻¹ ∘ [ i₁ +₁ D₁ i₁ ∘ σ , i₂ ∘ [ D₁ i₁ ∘ τ , later ∘ now ∘ i₂ ] ] ∘ w ∎