The Delay Monad is Commutative

module Monad.Instance.Delay.Commutative {o  e} (ambient : Ambient o  e) (D : DelayM ambient) where
  open Ambient ambient
  open HomReasoning
  open Equiv
  open MR C
  open M C
  open F-Coalgebra-Morphism using () renaming (f to u; commutes to u-commutes)
  open import Categories.Morphism.Properties C
  open Terminal using (!; !-unique; )

  open DelayM D
  open import Monad.Instance.Delay.Strong ambient D
  open Functor functor using () renaming (F₁ to D₁; identity to D-identity; homomorphism to D-homomorphism; F-resp-≈ to D-resp-≈)
  open RMonad kleisli using (extend; extend-≈) renaming (assoc to k-assoc; identityʳ to k-identityʳ; identityˡ to k-identityˡ)
  open Monad monad using (η; μ)
  open NaturalTransformation (StrongMonad.strengthen strongMonad) using () renaming (commute to τ-commute)
  commutativeMonad : Commutative braided strongMonad
  commutativeMonad = record { commutes = λ {X} {Y}  pullˡ (Kleisli⇒Monad⇒Kleisli kleisli _)  commutes'  pushˡ (sym (Kleisli⇒Monad⇒Kleisli kleisli _)) }
    where

We first introduce some helper definitions and lemmas:

      open τ-mod
      σ :  P  D₀ (proj₁ P) × (proj₂ P)  D₀ (proj₁ P × proj₂ P)
      σ (X , Y) = D₁ swap  (τ (Y , X))  swap
      σ-coalg :  (X Y : Obj)  F-Coalgebra-Morphism {F = (X × Y) +- } (record { A = D₀ X × Y ; α = distributeʳ⁻¹ {Y} {X} {D₀ X}  (out {X}  idC) }) (record { A = D₀ (X × Y) ; α = out {X × Y} })
      σ-coalg X Y = record { f = (σ (X , Y)) ; commutes = begin 
        out  (σ (X , Y))                                                                         ≈⟨ pullˡ (out-law swap)  
        ((swap +₁ D₁ swap)  out)  (τ (Y , X))  swap                                            ≈⟨ pullˡ (pullʳ (τ-law (Y , X)))  
        ((swap +₁ D₁ swap)  (idC +₁ (τ (Y , X)))  distributeˡ⁻¹  (idC  out))  swap           ≈⟨ pullʳ (pullʳ (pullʳ (sym swap∘⁂)))  
        (swap +₁ D₁ swap)  (idC +₁ (τ (Y , X)))  distributeˡ⁻¹  swap  (out  idC)             ≈⟨ refl⟩∘⟨ refl⟩∘⟨ pullˡ distributeˡ⁻¹∘swap  
        (swap +₁ D₁ swap)  (idC +₁ (τ (Y , X)))  ((swap +₁ swap)  distributeʳ⁻¹)  (out  idC) ≈⟨ pullˡ +₁∘+₁  
        (swap  idC +₁ D₁ swap  (τ (Y , X)))  ((swap +₁ swap)  distributeʳ⁻¹)  (out  idC)    ≈⟨ pullˡ (pullˡ +₁∘+₁)  
        (((swap  idC)  swap +₁ (D₁ swap  (τ (Y , X)))  swap)  distributeʳ⁻¹)  (out  idC)   ≈⟨ ((+₁-cong₂ (identityʳ ⟩∘⟨refl  swap∘swap) assoc) ⟩∘⟨refl) ⟩∘⟨refl  
        ((idC +₁ D₁ swap  (τ (Y , X))  swap)  distributeʳ⁻¹)  (out  idC)                     ≈⟨ assoc  
        (idC +₁ (σ (X , Y)))  distributeʳ⁻¹  (out  idC)                                         }
      σ-helper :  {X Y : Obj}  (σ (X , Y))  (out⁻¹  idC)  out⁻¹  (idC +₁ (σ (X , Y)))  distributeʳ⁻¹
      σ-helper {X} {Y} = begin 
        (σ (X , Y))  (out⁻¹  idC)                                                  ≈⟨ introˡ (_≅_.isoˡ out-≅)  
        (out⁻¹  out)  (σ (X , Y))  (out⁻¹  idC)                                  ≈⟨ pullʳ (pullˡ (u-commutes (σ-coalg X Y)))  
        out⁻¹  ((idC +₁ (σ (X , Y)))  distributeʳ⁻¹  (out  idC))  (out⁻¹  idC) ≈⟨ refl⟩∘⟨ (pullʳ (cancelʳ (⁂∘⁂  ⁂-cong₂ (_≅_.isoʳ out-≅) identity²  ⟨⟩-unique id-comm id-comm)))  
        out⁻¹  (idC +₁ (σ (X , Y)))  distributeʳ⁻¹                                 
      -- this is naturality of σ, i.e. it could be included from Categories.Monad.Strong.Properties but we reiterate the proof to save some imports
      σ-commute :  {U V W X : Obj} (f : U  V) (g : W  X)  (σ (V , X))  (extend (now  f)  g)  extend (now  (f  g))  σ (U , W)
      σ-commute {U} {V} {W} {X} f g = begin 
        (σ (V , X))  (D₁ f  g)                              ≈⟨ pullʳ (pullʳ swap∘⁂)  
        D₁ swap  (τ (X , V))  (g  extend (now  f))  swap ≈⟨ refl⟩∘⟨ (pullˡ (τ-commute (g , f)))  
        D₁ swap  (D₁ (g  f)  (τ (W , U)))  swap           ≈⟨ pullˡ (pullˡ (sym D-homomorphism))  
        (D₁ (swap  (g  f))  (τ (W , U)))  swap            ≈⟨ ((D-resp-≈ swap∘⁂) ⟩∘⟨refl) ⟩∘⟨refl  
        (D₁ ((f  g)  swap)  (τ (W , U)))  swap            ≈⟨ pushˡ D-homomorphism ⟩∘⟨refl  
        (D₁ (f  g)  D₁ swap  (τ (W , U)))  swap           ≈⟨ assoc²'  
        D₁ (f  g)  (σ (U , W))                              

We now proof commutativity by stability, i.e. by showing that both sides are solutions to some guarded morphism:

      commutes' :  {X Y}  extend (σ (X , Y))  (τ (D₀ X , Y))  extend (τ (X , Y))  (σ (X , D₀ Y)) 
      commutes' {X} {Y} = guarded-unique g (extend (σ (X , Y))  (τ (D₀ X , Y))) (extend (τ (X , Y))  (σ (X , D₀ Y))) guarded (fixpoint-eq fixpoint₁) (fixpoint-eq fixpoint₂)
        where
          w = (distributeʳ⁻¹ +₁ distributeʳ⁻¹)  distributeˡ⁻¹  (out  out)
          g = out⁻¹  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w
          guarded : is-guarded g
          guarded = [ idC +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w , (begin 
            (i₁ +₁ idC)  [ idC +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w                 ≈⟨ pullˡ ∘[]  
            [ (i₁ +₁ idC)  (idC +₁ D₁ i₁  (σ (X , Y))) , (i₁ +₁ idC)  i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w ≈⟨ ([]-cong₂ +₁∘+₁ (pullˡ +₁∘i₂)) ⟩∘⟨refl 
            [ (i₁  idC +₁ idC  D₁ i₁  (σ (X , Y))) , (i₂  idC)  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w          ≈⟨ ([]-cong₂ (+₁-cong₂ identityʳ identityˡ) (identityʳ ⟩∘⟨refl)) ⟩∘⟨refl 
            [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w                                ≈⟨ sym (cancelˡ (_≅_.isoʳ out-≅)) 
            out  out⁻¹  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w                  )

          fixpoint₁ : extend (σ (X , Y))  (τ (D₀ X , Y))  out⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (σ (X , Y))  (τ (D₀ X , Y)) ] ]  w
          fixpoint₁ = Iso⇒Mono (_≅_.iso out-≅) (extend (σ (X , Y))  (τ (D₀ X , Y))) (out⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (σ (X , Y))  (τ (D₀ X , Y)) ] ]  w) (begin 
            out  extend (σ (X , Y))  (τ (D₀ X , Y))                                                                                                                                                                                           ≈⟨ pullˡ (extendlaw (σ (X , Y)))  
            ([ out  (σ (X , Y)) , i₂  extend' (σ (X , Y)) ]  out)  (τ (D₀ X , Y))                                                                                                                                                           ≈⟨ pullʳ (τ-law (D₀ X , Y)) 
            [ out  (σ (X , Y)) , i₂  extend' (σ (X , Y)) ]  (idC +₁ (τ (D₀ X , Y)))  distributeˡ⁻¹  (idC  out)                                                                                                                            ≈⟨ pullˡ []∘+₁ 
            [ (out  (σ (X , Y)))  idC , (i₂  extend' (σ (X , Y)))  (τ (D₀ X , Y)) ]  distributeˡ⁻¹  (idC  out)                                                                                                                           ≈⟨ ([]-cong₂ (identityʳ  u-commutes (σ-coalg X Y)) assoc) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹  (out  idC) , i₂  extend' (σ (X , Y))  (τ (D₀ X , Y)) ]  distributeˡ⁻¹  (idC  out)                                                                                                    ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ⁂-cong₂ (sym (_≅_.isoˡ out-≅)) refl 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹  (out  idC) , i₂  extend' (σ (X , Y))  (τ (D₀ X , Y)) ]  distributeˡ⁻¹  (out⁻¹  out  out)                                                                                            ≈⟨ sym (refl⟩∘⟨ refl⟩∘⟨ (⁂∘⁂  ⁂-cong₂ refl (elimˡ ([]-unique id-comm-sym id-comm-sym)))) 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹  (out  idC) , i₂  extend' (σ (X , Y))  (τ (D₀ X , Y)) ]  distributeˡ⁻¹  (out⁻¹  (idC +₁ idC))  (out  out)                                                                           ≈⟨ refl⟩∘⟨ pullˡ (sym (distributeˡ⁻¹-natural out⁻¹ idC idC)) 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹  (out  idC) , i₂  extend' (σ (X , Y))  (τ (D₀ X , Y)) ]  (((out⁻¹  idC) +₁ (out⁻¹  idC))  distributeˡ⁻¹)  (out  out)                                                               ≈⟨ pullˡ (pullˡ []∘+₁) 
            ([ ((idC +₁ (σ (X , Y)))  distributeʳ⁻¹  (out  idC))  (out⁻¹  idC) , (i₂  extend' (σ (X , Y))  (τ (D₀ X , Y)))  (out⁻¹  idC) ]  distributeˡ⁻¹)  (out  out)                                                              ≈⟨ assoc  ([]-cong₂ (pullʳ (cancelʳ (⁂∘⁂  ⁂-cong₂ (_≅_.isoʳ out-≅) identity²  ⟨⟩-unique id-comm id-comm))) (refl⟩∘⟨ (⁂-cong₂ refl (sym D-identity))  (pullʳ (pullʳ (τ-commute (out⁻¹ , idC)))))) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹ , i₂  extend' (σ (X , Y))  D₁ (out⁻¹  idC)  (τ (X + D₀ X , Y)) ]  distributeˡ⁻¹  (out  out)                                                                                           ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ (pullˡ (sym k-assoc))  refl⟩∘⟨ ((extend-≈ (pullˡ k-identityʳ)) ⟩∘⟨refl))) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹ , i₂  extend' (σ (X , Y)  (out⁻¹  idC))  (τ (X + D₀ X , Y)) ]  distributeˡ⁻¹  (out  out)                                                                                              ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ((extend-≈ σ-helper) ⟩∘⟨refl))) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹ , i₂  extend' (out⁻¹  (idC +₁ (σ (X , Y)))  distributeʳ⁻¹)  (τ (X + D₀ X , Y)) ]  distributeˡ⁻¹  (out  out)                                                                           ≈˘⟨ ([]-cong₂ refl (refl⟩∘⟨ ((sym k-assoc  extend-≈ (pullˡ k-identityʳ)  extend-≈ assoc) ⟩∘⟨refl))) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹ , i₂  (extend' (out⁻¹  (idC +₁ (σ (X , Y))))  D₁ distributeʳ⁻¹)  (τ (X + D₀ X , Y)) ]  distributeˡ⁻¹  (out  out)                                                                      ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ pullʳ helper₁)) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y)))  distributeʳ⁻¹ , i₂  extend' (out⁻¹  (idC +₁ (σ (X , Y))))  [ D₁ i₁  (τ (X , Y)) , D₁ i₂  (τ (D₀ X , Y)) ]  distributeʳ⁻¹ ]  distributeˡ⁻¹  (out  out)                                             ≈˘⟨ pullˡ ([]∘+₁  []-cong₂ refl assoc²') 
            [ (idC +₁ (σ (X , Y))) , i₂  extend' (out⁻¹  (idC +₁ (σ (X , Y))))  [ D₁ i₁  (τ (X , Y)) , D₁ i₂  (τ (D₀ X , Y)) ] ]  (distributeʳ⁻¹ +₁ distributeʳ⁻¹)  distributeˡ⁻¹  (out  out)                                          ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ∘[])) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y))) , i₂  [ extend' (out⁻¹  (idC +₁ (σ (X , Y))))  D₁ i₁  (τ (X , Y)) , extend' (out⁻¹  (idC +₁ (σ (X , Y))))  D₁ i₂  (τ (D₀ X , Y)) ] ]  (distributeʳ⁻¹ +₁ distributeʳ⁻¹)  distributeˡ⁻¹  (out  out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ (pullˡ ((sym k-assoc)  extend-≈ (pullˡ k-identityʳ))) (pullˡ ((sym k-assoc)  extend-≈ (pullˡ k-identityʳ)))))) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y))) , i₂  [ extend' ((out⁻¹  (idC +₁ (σ (X , Y))))  i₁)  (τ (X , Y)) , extend' ((out⁻¹  (idC +₁ (σ (X , Y))))  i₂)  (τ (D₀ X , Y)) ] ]  (distributeʳ⁻¹ +₁ distributeʳ⁻¹)  distributeˡ⁻¹  (out  out)   ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ ((extend-≈ (pullʳ +₁∘i₁)) ⟩∘⟨refl) ((extend-≈ (pullʳ +₁∘i₂)) ⟩∘⟨refl)))) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y))) , i₂  [ extend' (out⁻¹  i₁  idC)  (τ (X , Y)) , extend' (out⁻¹  i₂  (σ (X , Y)))  (τ (D₀ X , Y)) ] ]  (distributeʳ⁻¹ +₁ distributeʳ⁻¹)  distributeˡ⁻¹  (out  out)                                 ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ (elimˡ ((extend-≈ (refl⟩∘⟨ identityʳ))  k-identityˡ)) ((extend-≈ sym-assoc) ⟩∘⟨refl)))) ⟩∘⟨refl 
            [ (idC +₁ (σ (X , Y))) , i₂  [ (τ (X , Y)) , extend' (  (σ (X , Y)))  (τ (D₀ X , Y)) ] ]  (distributeʳ⁻¹ +₁ distributeʳ⁻¹)  distributeˡ⁻¹  (out  out)                                                                       ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ refl ((sym (▷∘extendˡ (σ (X , Y)))) ⟩∘⟨refl  assoc)))) ⟩∘⟨refl 
            [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (σ (X , Y))  (τ (D₀ X , Y)) ] ]  w                                                                                                                                         ≈˘⟨ cancelˡ (_≅_.isoʳ out-≅) 
            out  out⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (σ (X , Y))  (τ (D₀ X , Y)) ] ]  w                                                                                                                           )
            where
            helper₁ : (D₁ distributeʳ⁻¹)  (τ (X + D₀ X , Y))  [ D₁ i₁  (τ (X , Y)) , D₁ i₂  (τ (D₀ X , Y)) ]  distributeʳ⁻¹
            helper₁ = Iso⇒Epi (IsIso.iso isIsoʳ) ((D₁ distributeʳ⁻¹)  (τ (X + D₀ X , Y))) ([ D₁ i₁  (τ (X , Y)) , D₁ i₂  (τ (D₀ X , Y)) ]  distributeʳ⁻¹) (begin 
              ((D₁ distributeʳ⁻¹)  (τ (X + D₀ X , Y)))  distributeʳ                                                                   ≈⟨ ∘[]  
              [ ((D₁ distributeʳ⁻¹)  (τ (X + D₀ X , Y)))  (i₁  idC) , ((D₁ distributeʳ⁻¹)  (τ (X + D₀ X , Y)))  (i₂  idC) ]       ≈⟨ []-cong₂ (refl⟩∘⟨ (⁂-cong₂ refl (sym D-identity))) (refl⟩∘⟨ (⁂-cong₂ refl (sym D-identity)))  
              [ ((D₁ distributeʳ⁻¹)  (τ (X + D₀ X , Y)))  (i₁  D₁ idC) , ((D₁ distributeʳ⁻¹)  (τ (X + D₀ X , Y)))  (i₂  D₁ idC) ] ≈⟨ []-cong₂ (pullʳ (τ-commute (i₁ , idC))) (pullʳ (τ-commute (i₂ , idC)))  
              [ (D₁ distributeʳ⁻¹)  D₁ (i₁  idC)  (τ (X , Y)) , (D₁ distributeʳ⁻¹)  D₁ (i₂  idC)  (τ (D₀ X , Y)) ]                ≈⟨ []-cong₂ (pullˡ (sym D-homomorphism)) (pullˡ (sym D-homomorphism))  
              [ D₁ (distributeʳ⁻¹  (i₁  idC))  (τ (X , Y)) , D₁ (distributeʳ⁻¹  (i₂  idC))  (τ (D₀ X , Y)) ]                      ≈⟨ []-cong₂ (D-resp-≈ distributeʳ⁻¹-i₁ ⟩∘⟨refl) ((D-resp-≈ distributeʳ⁻¹-i₂) ⟩∘⟨refl)  
              [ D₁ i₁  (τ (X , Y)) , D₁ i₂  (τ (D₀ X , Y)) ]                                                                          ≈˘⟨ cancelʳ (IsIso.isoˡ isIsoʳ)  
              ([ D₁ i₁  (τ (X , Y)) , D₁ i₂  (τ (D₀ X , Y)) ]  distributeʳ⁻¹)  distributeʳ                                          )

          fixpoint₂ : extend (τ (X , Y))  (σ (X , D₀ Y))  out⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  w
          fixpoint₂ = Iso⇒Mono ((_≅_.iso out-≅)) (extend (τ (X , Y))  (σ (X , D₀ Y))) (out⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  w) (begin 
            out  extend (τ (X , Y))  (σ (X , D₀ Y))                                                                                                                                                                                         ≈⟨ pullˡ (extendlaw (τ (X , Y)))  
            ([ out  (τ (X , Y)) , i₂  extend (τ (X , Y)) ]  out)  (σ (X , D₀ Y))                                                                                                                                                          ≈⟨ pullʳ (u-commutes (σ-coalg X (D₀ Y)))  
            [ out  (τ (X , Y)) , i₂  extend (τ (X , Y)) ]  (idC +₁ (σ (X , D₀ Y)))  distributeʳ⁻¹  (out  idC)                                                                                                                           ≈⟨ pullˡ []∘+₁  
            [ (out  (τ (X , Y)))  idC , (i₂  extend (τ (X , Y)))  (σ (X , D₀ Y)) ]  distributeʳ⁻¹  (out  idC)                                                                                                                          ≈⟨ ([]-cong₂ (identityʳ  τ-law (X , Y)) assoc) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹  (idC  out) , i₂  extend (τ (X , Y))  (σ (X , D₀ Y)) ]  distributeʳ⁻¹  (out  idC)                                                                                                   ≈⟨ refl⟩∘⟨ refl⟩∘⟨ sym (⁂∘⁂  ⁂-cong₂ (elimˡ ([]-unique id-comm-sym id-comm-sym)) (_≅_.isoˡ out-≅))  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹  (idC  out) , i₂  extend (τ (X , Y))  (σ (X , D₀ Y)) ]  distributeʳ⁻¹  ((idC +₁ idC)  out⁻¹)  (out  out)                                                                          ≈⟨ refl⟩∘⟨ (pullˡ (sym (distributeʳ⁻¹-natural out⁻¹ idC idC)))  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹  (idC  out) , i₂  extend (τ (X , Y))  (σ (X , D₀ Y)) ]  (((idC  out⁻¹) +₁ (idC  out⁻¹))  distributeʳ⁻¹)  (out  out)                                                              ≈⟨ pullˡ (pullˡ []∘+₁)  
            ([ ((idC +₁ (τ (X , Y)))  distributeˡ⁻¹  (idC  out))  (idC  out⁻¹) , (i₂  extend (τ (X , Y))  (σ (X , D₀ Y)))  (idC  out⁻¹) ]  distributeʳ⁻¹)  (out  out)                                                             ≈⟨ assoc  ([]-cong₂ (pullʳ (cancelʳ (⁂∘⁂  ⁂-cong₂ identity² (_≅_.isoʳ out-≅)  ⟨⟩-unique id-comm id-comm))) (refl⟩∘⟨ (⁂-cong₂ (sym D-identity) refl))) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹ , (i₂  extend (τ (X , Y))  (σ (X , D₀ Y)))  (D₁ idC  out⁻¹) ]  distributeʳ⁻¹  (out  out)                                                                                            ≈⟨ ([]-cong₂ refl (pullʳ (pullʳ (σ-commute idC out⁻¹)))) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹ , i₂  extend (τ (X , Y))  D₁ (idC  out⁻¹)  (σ (X , Y + D₀ Y)) ]  distributeʳ⁻¹  (out  out)                                                                                          ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ (pullˡ ((sym k-assoc)  extend-≈ (pullˡ k-identityʳ))))) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹ , i₂  extend (τ (X , Y)  (idC  out⁻¹))  (σ (X , Y + D₀ Y)) ]  distributeʳ⁻¹  (out  out)                                                                                             ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ((extend-≈ (τ-helper (X , Y))) ⟩∘⟨refl))) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹ , i₂  extend (out⁻¹  (idC +₁ (τ (X , Y)))  distributeˡ⁻¹)  (σ (X , Y + D₀ Y)) ]  distributeʳ⁻¹  (out  out)                                                                          ≈˘⟨ ([]-cong₂ refl (refl⟩∘⟨ pullˡ ((sym k-assoc)  (extend-≈ (pullˡ k-identityʳ)  extend-≈ assoc)))) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹ , i₂  extend (out⁻¹  (idC +₁ (τ (X , Y))))  D₁ distributeˡ⁻¹  (σ (X , Y + D₀ Y)) ]  distributeʳ⁻¹  (out  out)                                                                       ≈⟨ ([]-cong₂ refl ((refl⟩∘⟨ (refl⟩∘⟨ helper₂))  sym assoc²')) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y)))  distributeˡ⁻¹ , (i₂  extend (out⁻¹  (idC +₁ (τ (X , Y))))  [ D₁ i₁  (σ (X , Y)) , D₁ i₂  (σ (X , D₀ Y)) ])  distributeˡ⁻¹ ]  distributeʳ⁻¹  (out  out)                                          ≈˘⟨ []∘+₁ ⟩∘⟨refl  
            ([ (idC +₁ (τ (X , Y))) , i₂  extend (out⁻¹  (idC +₁ (τ (X , Y))))  [ D₁ i₁  (σ (X , Y)) , D₁ i₂  (σ (X , D₀ Y)) ] ]  (distributeˡ⁻¹ +₁ distributeˡ⁻¹))  distributeʳ⁻¹  (out  out)                                       ≈⟨ assoc  ([]-cong₂ refl (refl⟩∘⟨ ∘[])) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y))) , i₂  [ extend (out⁻¹  (idC +₁ (τ (X , Y))))  D₁ i₁  (σ (X , Y)) , extend (out⁻¹  (idC +₁ (τ (X , Y))))  D₁ i₂  (σ (X , D₀ Y)) ] ]  (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  distributeʳ⁻¹  (out  out) ≈⟨ ([]-cong₂ refl (refl⟩∘⟨ ([]-cong₂ (pullˡ (sym k-assoc  extend-≈ (pullˡ k-identityʳ))) (pullˡ (sym k-assoc  extend-≈ (pullˡ k-identityʳ)))))) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y))) , i₂  [ extend ((out⁻¹  (idC +₁ (τ (X , Y))))  i₁)  (σ (X , Y)) , extend ((out⁻¹  (idC +₁ (τ (X , Y))))  i₂)  (σ (X , D₀ Y)) ] ]  (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  distributeʳ⁻¹  (out  out)   ≈⟨ []-cong₂ refl (refl⟩∘⟨ []-cong₂ (extend-≈ (pullʳ inject₁) ⟩∘⟨refl) (extend-≈ (pullʳ inject₂) ⟩∘⟨refl)) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y))) , i₂  [ extend (out⁻¹  i₁  idC)  (σ (X , Y)) , extend (out⁻¹  i₂  (τ (X , Y)))  (σ (X , D₀ Y)) ] ]  (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  distributeʳ⁻¹  (out  out)                                 ≈⟨ []-cong₂ refl (refl⟩∘⟨ []-cong₂ (elimˡ (extend-≈ (refl⟩∘⟨ identityʳ)  k-identityˡ)) (extend-≈ sym-assoc ⟩∘⟨refl  sym (pullˡ (▷∘extendˡ (τ (X , Y)))))) ⟩∘⟨refl  
            [ (idC +₁ (τ (X , Y))) , i₂  [ (σ (X , Y)) ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  distributeʳ⁻¹  (out  out)                                                                        ≈⟨ helper₃  
            [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  w                                                                                                                                       ≈˘⟨ cancelˡ (_≅_.isoʳ out-≅)  
            out  out⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  w                                                                                                                         )
            where
            helper₂ : (D₁ distributeˡ⁻¹)  (σ (X , Y + D₀ Y))  [ D₁ i₁  (σ (X , Y)) , D₁ i₂  (σ (X , D₀ Y)) ]  distributeˡ⁻¹
            helper₂ = Iso⇒Epi (IsIso.iso isIsoˡ) ((D₁ distributeˡ⁻¹)  (σ (X , Y + D₀ Y))) ([ D₁ i₁  (σ (X , Y)) , D₁ i₂  (σ (X , D₀ Y)) ]  distributeˡ⁻¹) (begin 
              ((D₁ distributeˡ⁻¹)  (σ (X , Y + D₀ Y)))  distributeˡ                                                                   ≈⟨ ∘[]  
              [ ((D₁ distributeˡ⁻¹)  (σ (X , Y + D₀ Y)))  (idC  i₁) , ((D₁ distributeˡ⁻¹)  (σ (X , Y + D₀ Y)))  (idC  i₂) ]       ≈⟨ []-cong₂ (refl⟩∘⟨ ⁂-cong₂ (sym D-identity) refl) (refl⟩∘⟨ ⁂-cong₂ (sym D-identity) refl)  
              [ ((D₁ distributeˡ⁻¹)  (σ (X , Y + D₀ Y)))  (D₁ idC  i₁) , ((D₁ distributeˡ⁻¹)  (σ (X , Y + D₀ Y)))  (D₁ idC  i₂) ] ≈⟨ []-cong₂ (pullʳ (σ-commute idC i₁)) (pullʳ (σ-commute idC i₂))  
              [ (D₁ distributeˡ⁻¹)  D₁ (idC  i₁)  (σ (X , Y)) , (D₁ distributeˡ⁻¹)  D₁ (idC  i₂)  (σ (X , D₀ Y)) ]                ≈⟨ []-cong₂ (pullˡ (sym D-homomorphism)) (pullˡ (sym D-homomorphism))  
              [ D₁ (distributeˡ⁻¹  (idC  i₁))  (σ (X , Y)) , D₁ (distributeˡ⁻¹  (idC  i₂))  (σ (X , D₀ Y)) ]                      ≈⟨ []-cong₂ (D-resp-≈ distributeˡ⁻¹-i₁ ⟩∘⟨refl) (D-resp-≈ distributeˡ⁻¹-i₂ ⟩∘⟨refl)  
              [ D₁ i₁  (σ (X , Y)) , D₁ i₂  (σ (X , D₀ Y)) ]                                                                          ≈˘⟨ cancelʳ (IsIso.isoˡ isIsoˡ)  
              ([ D₁ i₁  (σ (X , Y)) , D₁ i₂  (σ (X , D₀ Y)) ]  distributeˡ⁻¹)  distributeˡ                                          )
            helper₃ : [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  distributeʳ⁻¹  (out {X}  out {Y})  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  w
            helper₃ = begin 
              [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  distributeʳ⁻¹  (out {X}  out {Y})                        ≈⟨ refl⟩∘⟨ helper  
              [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  [ [ i₁  i₁ , i₂  i₁ ] , [ (i₁  i₂) , (i₂  i₂) ] ]  w                                     ≈⟨ pullˡ ∘[] 
              [ [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  [ i₁  i₁ , i₂  i₁ ] 
              , [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  [ (i₁  i₂) , (i₂  i₂) ] ]  w                                                             ≈⟨ ([]-cong₂ ∘[] ∘[]) ⟩∘⟨refl 
              [ [ [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  i₁  i₁ , [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  i₂  i₁ ] 
              , [ [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  (i₁  i₂) 
                , [ idC +₁ (τ (X , Y)) , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  (i₂  i₂) ] ]  w                                                                         ≈⟨ ([]-cong₂ ([]-cong₂ (pullˡ inject₁) (pullˡ inject₂  assoc)) ([]-cong₂ (pullˡ inject₁) (pullˡ inject₂  assoc))) ⟩∘⟨refl 
              [ [ (idC +₁ (τ (X , Y)))  i₁ , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ]  i₁ ] , [ (idC +₁ (τ (X , Y)))  i₂ , i₂  [ D₁ swap  (τ (Y , X))  swap ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ]  i₂ ] ]  w ≈⟨ ([]-cong₂ ([]-cong₂ (+₁∘i₁  identityʳ) (refl⟩∘⟨ inject₁)) ([]-cong₂ +₁∘i₂ (refl⟩∘⟨ inject₂))) ⟩∘⟨refl 
              [ [ i₁ , i₂  (σ (X , Y)) ] , [ i₂  (τ (X , Y)) , i₂    extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  w                                                                                                  ≈˘⟨ ([]-cong₂ ([]-cong₂ identityʳ refl) ∘[]) ⟩∘⟨refl 
              [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   extend (τ (X , Y))  (σ (X , D₀ Y)) ] ]  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ˡ []∘+₁  
                [ (i₁ +₁ i₁)  distributeʳ⁻¹ , (i₂ +₁ i₂)  distributeʳ⁻¹ ]  distributeˡ⁻¹  (out  out)                                                                    ≈⟨ ([]-cong₂ ((+₁-cong₂ (sym distributeˡ⁻¹-i₁) (sym distributeˡ⁻¹-i₁)) ⟩∘⟨refl) ((+₁-cong₂ (sym distributeˡ⁻¹-i₂) (sym distributeˡ⁻¹-i₂)) ⟩∘⟨refl)) ⟩∘⟨refl  
                [ (distributeˡ⁻¹  (idC  i₁) +₁ distributeˡ⁻¹  (idC  i₁))  distributeʳ⁻¹ 
                , (distributeˡ⁻¹  (idC  i₂) +₁ distributeˡ⁻¹  (idC  i₂))  distributeʳ⁻¹ ]  distributeˡ⁻¹  (out  out)                                                 ≈⟨ sym (([]-cong₂ (pullˡ +₁∘+₁) (pullˡ +₁∘+₁)) ⟩∘⟨refl)  
                [ (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  ((idC  i₁) +₁ (idC  i₁))  distributeʳ⁻¹ 
                , (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  ((idC  i₂) +₁ (idC  i₂))  distributeʳ⁻¹ ]  distributeˡ⁻¹  (out  out)                                              ≈⟨ sym (pullˡ ∘[]) 
                (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  [ ((idC  i₁) +₁ (idC  i₁))  distributeʳ⁻¹ , ((idC  i₂) +₁ (idC  i₂))  distributeʳ⁻¹ ]  distributeˡ⁻¹  (out  out) ≈⟨ refl⟩∘⟨ []-cong₂ (distributeʳ⁻¹-natural i₁ idC idC) (distributeʳ⁻¹-natural i₂ idC idC) ⟩∘⟨refl  
                (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  [ distributeʳ⁻¹  ((idC +₁ idC)  i₁) , distributeʳ⁻¹  ((idC +₁ idC)  i₂) ]  distributeˡ⁻¹  (out  out)               ≈⟨ refl⟩∘⟨ (sym (pullˡ ∘[]))  
                (distributeˡ⁻¹ +₁ distributeˡ⁻¹)  distributeʳ⁻¹  [ ((idC +₁ idC)  i₁) , ((idC +₁ idC)  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ʳ⁻¹  [ (idC  i₁) , (idC  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⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   f ] ]  w  f  extend [ now , f ]  g
          fixpoint-eq {f} fix = begin 
            f                                                                                                                                                                                           ≈⟨ fix  
            out⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) ,   f ] ]  w                                                                                                                           ≈˘⟨ refl⟩∘⟨ []-cong₂ refl (refl⟩∘⟨ ([]-cong₂ refl (pullʳ inject₂))) ⟩∘⟨refl 
            out⁻¹  [ idC +₁ (σ (X , Y)) , i₂  [ (τ (X , Y)) , (  [ now , f ])  i₂ ] ]  w                                                                                                          ≈˘⟨ refl⟩∘⟨ []-cong₂ refl (sym ∘[]  refl⟩∘⟨ []-cong₂ (elimˡ (extend-≈ inject₁  k-identityˡ)) (pullˡ k-identityʳ)) ⟩∘⟨refl 
            out⁻¹  [ idC +₁ (σ (X , Y)) , [ i₂  extend ([ now , f ]  i₁)  (τ (X , Y)) , i₂  extend (  [ now , f ])  now  i₂ ] ]  w                                                            ≈˘⟨ refl⟩∘⟨ []-cong₂ ([]-cong₂ (sym identityʳ) (refl⟩∘⟨ (elimˡ ((extend-≈ inject₁)  k-identityˡ)))) ([]-cong₂ (pullʳ (pullˡ ((sym k-assoc)  extend-≈ (pullˡ k-identityʳ)))) (pullʳ (pullˡ (▷∘extendʳ [ now , f ])))) ⟩∘⟨refl 
            out⁻¹  [ [ i₁ , i₂  extend ([ now , f ]  i₁)  (σ (X , Y)) ] , [ (i₂  extend [ now , f ])  D₁ i₁  (τ (X , Y)) , (i₂  extend [ now , f ])    now  i₂ ] ]  w                      ≈˘⟨ refl⟩∘⟨ []-cong₂ ([]-cong₂ inject₁ (pullʳ (pullˡ ((sym k-assoc)  extend-≈ (pullˡ k-identityʳ))))) ∘[] ⟩∘⟨refl 
            out⁻¹  [ [ [ i₁ , out  f ]  i₁ , (i₂  extend [ now , f ])  D₁ i₁  (σ (X , Y)) ] , (i₂  extend [ now , f ])  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w                            ≈˘⟨ refl⟩∘⟨ (([]-cong₂ []∘+₁ (pullˡ inject₂)) ⟩∘⟨refl) 
            out⁻¹  [ [ [ i₁ , out  f ] , i₂  extend [ now , f ] ]  (i₁ +₁ D₁ i₁  (σ (X , Y))) , [ [ i₁ , out  f ] , i₂  extend [ now , f ] ]  i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w ≈˘⟨ refl⟩∘⟨ (pullˡ ∘[]) 
            out⁻¹  [ [ i₁ , out  f ] , i₂  extend [ now , f ] ]  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w                                                    ≈⟨ Iso⇒Mono (_≅_.iso out-≅) (out⁻¹  [ [ i₁ , out  f ] , i₂  extend [ now , f ] ]  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w) (extend [ now , f ]  out⁻¹  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w) helper 
            extend [ now , f ]  out⁻¹  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w                                                                                 
            where
              helper = begin 
                out  out⁻¹  [ [ i₁ , out  f ] , i₂  extend [ now , f ] ]  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w    ≈⟨ cancelˡ (_≅_.isoʳ out-≅)  
                [ [ i₁ , out  f ] , i₂  extend [ now , f ] ]  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w                  ≈˘⟨ ([]-cong₂ (∘[]  []-cong₂ unitlaw refl) refl) ⟩∘⟨refl  
                [ out  [ now , f ] , i₂  extend [ now , f ] ]  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w                 ≈˘⟨ pullʳ (cancelˡ (_≅_.isoʳ out-≅))  
                ([ out  [ now , f ] , i₂  extend [ now , f ] ]  out)  out⁻¹  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w ≈˘⟨ pullˡ (extendlaw [ now , f ])  
                out  extend [ now , f ]  out⁻¹  [ i₁ +₁ D₁ i₁  (σ (X , Y)) , i₂  [ D₁ i₁  (τ (X , Y)) ,   now  i₂ ] ]  w