The Delay Monad is Strong

module Monad.Instance.Delay.Strong {o  e} (ambient : Ambient o  e) (D : DelayM ambient) where
  open Ambient ambient
  open HomReasoning
  open Equiv
  open MP C
  open MR C
  open M C
  open F-Coalgebra-Morphism renaming (f to u)
  open DelayM D
  open Functor
  open RMonad kleisli using (extend; extend-≈) renaming (assoc to k-assoc; identityʳ to k-identityʳ)
  open Monad monad using (η; μ)

First some facts about strength:

  module τ-mod (P : Category.Obj (CProduct C C)) where
    private
      X = proj₁ P
      Y = proj₂ P
    open Terminal (coalgebras (X × Y))

    τ : X × D₀ Y  D₀ (X × Y)
    τ = u (! {A = record { A = X × D₀ Y ; α = distributeˡ⁻¹  (idC  out) }})

    τ-law : out  τ  (idC +₁ τ)  distributeˡ⁻¹  (idC  out)
    τ-law = commutes (! {A = record { A = X × D₀ Y ; α = distributeˡ⁻¹  (idC  out) }})

    τ-helper : τ  (idC  out⁻¹)  out⁻¹  (idC +₁ τ)  distributeˡ⁻¹
    τ-helper = begin 
      τ  (idC  out⁻¹)                                                  ≈⟨ introˡ (_≅_.isoˡ out-≅)  
      (out⁻¹  out)  τ  (idC  out⁻¹)                                  ≈⟨ pullʳ (pullˡ τ-law) 
      out⁻¹  ((idC +₁ τ)  distributeˡ⁻¹  (idC  out))  (idC  out⁻¹) ≈⟨ refl⟩∘⟨ (assoc  refl⟩∘⟨ assoc) 
      out⁻¹  (idC +₁ τ)  distributeˡ⁻¹  (idC  out)  (idC  out⁻¹)   ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (elimʳ (⁂∘⁂  (⁂-cong₂ identity² (_≅_.isoʳ out-≅))  ((⟨⟩-cong₂ identityˡ identityˡ)  ⁂-η)))) 
      out⁻¹  (idC +₁ τ)  distributeˡ⁻¹                                 

    τ-now : τ  (idC  now)  now
    τ-now = begin 
      τ  (idC  now)                                   ≈⟨ refl⟩∘⟨ sym (⁂∘⁂  (⁂-cong₂ identity² refl))  
      τ  (idC  out⁻¹)  (idC  i₁)                    ≈⟨ pullˡ τ-helper 
      (out⁻¹  (idC +₁ τ)  distributeˡ⁻¹)  (idC  i₁) ≈⟨ pullʳ (pullʳ distributeˡ⁻¹-i₁) 
      out⁻¹  (idC +₁ τ)  i₁                           ≈⟨ refl⟩∘⟨ +₁∘i₁ 
      out⁻¹  i₁  idC                                  ≈⟨ refl⟩∘⟨ identityʳ 
      now                                               
    
    ▷∘τ : τ  (idC  )    τ
    ▷∘τ = begin 
      τ  (idC  )                                     ≈⟨ refl⟩∘⟨ (sym (⁂∘⁂  ⁂-cong₂ identity² refl))  
      τ  (idC  out⁻¹)  (idC  i₂)                    ≈⟨ pullˡ τ-helper  
      (out⁻¹  (idC +₁ τ)  distributeˡ⁻¹)  (idC  i₂) ≈⟨ pullʳ (pullʳ distributeˡ⁻¹-i₂)  
      out⁻¹  (idC +₁ τ)  i₂                           ≈⟨ refl⟩∘⟨ +₁∘i₂  
      out⁻¹  i₂  τ                                    ≈⟨ sym-assoc  
        τ                                             

    τ-unique : (t : X × D₀ Y  D₀ (X × Y))  (out  t  (idC +₁ t)  distributeˡ⁻¹  (idC  out))  t  τ
    τ-unique t t-commutes = sym (!-unique (record { f = t ; commutes = t-commutes }))
  open τ-mod

Now we proof strength by coinduction and above properties:

  strength : Strength monoidal monad
  Strength.strengthen strength = ntHelper (record { η = τ; commute = commute' })
    where
    commute' :  {P₁ : Category.Obj (CProduct C C)} {P₂ : Category.Obj (CProduct C C)} (fg : _[_,_] (CProduct C C) P₁ P₂) 
       τ P₂  ((proj₁ fg)  extend (now  (proj₂ fg)))  extend (now  ((proj₁ fg)  (proj₂ fg)))  τ P₁
    commute' {(U , V)} {(W , X)} (f , g) = by-coinduction ((((f  g) +₁ idC)  distributeˡ⁻¹)  (idC  out)) coind₁ coind₂ 
      where
      coind₁ : out  τ (W , X)  (f  extend (now  g))  (idC +₁ (τ (W , X)  (f  extend (now  g))))  ((f  g +₁ idC)  distributeˡ⁻¹)  (idC  out)
      coind₁ = begin 
        out  τ (W , X)  (f  extend (now  g))                                                       ≈⟨ pullˡ (τ-law (W , X))  
        ((idC +₁ τ (W , X))  distributeˡ⁻¹  (idC  out))  (f  extend (now  g))                    ≈⟨ pullʳ (pullʳ ⁂∘⁂)  
        (idC +₁ τ (W , X))  distributeˡ⁻¹  (idC  f  out  extend (now  g))                        ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (⁂-cong₂ identityˡ (extendlaw (now  g))))  
        (idC +₁ τ (W , X))  distributeˡ⁻¹  (f  [ out  now  g , i₂  extend (now  g) ]  out)     ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (⁂-cong₂ refl (([]-cong₂ (pullˡ unitlaw) refl) ⟩∘⟨refl)))  
        (idC +₁ τ (W , X))  distributeˡ⁻¹  (f  [ i₁  g , i₂  extend (now  g) ]  out)            ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (⁂-cong₂ (sym identityʳ) refl))  
        (idC +₁ τ (W , X))  distributeˡ⁻¹  (f  idC  (g +₁ extend (now  g))  out)                 ≈⟨ sym (pullʳ (pullʳ ⁂∘⁂))  
        ((idC +₁ τ (W , X))  distributeˡ⁻¹  (f  (g +₁ extend (now  g))))  (idC  out)             ≈⟨ (refl⟩∘⟨ (sym (distributeˡ⁻¹-natural f g (extend (now  g))))) ⟩∘⟨refl  
        ((idC +₁ τ (W , X))  ((f  g) +₁ (f  extend (now  g)))  distributeˡ⁻¹)  (idC  out)       ≈⟨ (pullˡ +₁∘+₁) ⟩∘⟨refl  
        ((idC  (f  g) +₁ τ (W , X)  (f  extend (now  g)))  distributeˡ⁻¹)  (idC  out)          ≈⟨ sym (((+₁-cong₂ refl identityʳ) ⟩∘⟨refl) ⟩∘⟨refl)  
        ((idC  (f  g) +₁ (τ (W , X)  (f  extend (now  g)))  idC)  distributeˡ⁻¹)  (idC  out)  ≈⟨ sym (pullˡ (pullˡ +₁∘+₁))  
        (idC +₁ (τ (W , X)  (f  extend (now  g))))  ((f  g +₁ idC)  distributeˡ⁻¹)  (idC  out) 
      coind₂ : out  extend (now  (f  g))  τ (U , V)  (idC +₁ (extend (now  (f  g))  τ (U , V)))  (((f  g) +₁ idC)  distributeˡ⁻¹)  (idC  out)
      coind₂ = begin 
        out  extend (now  (f  g))  τ (U , V)                                                          ≈⟨ pullˡ (extendlaw (now  (f  g)))  
        ([ out  now  (f  g) , i₂  extend (now  (f  g)) ]  out)  τ (U , V)                         ≈⟨ (([]-cong₂ (pullˡ unitlaw) refl) ⟩∘⟨refl) ⟩∘⟨refl 
        ([ i₁  (f  g) , i₂  extend (now  (f  g)) ]  out)  τ (U , V)                                ≈⟨ pullʳ (τ-law (U , V)) 
        ((f  g) +₁ (extend (now  (f  g))))  (idC +₁ τ (U , V))  distributeˡ⁻¹  (idC  out)          ≈⟨ sym-assoc  sym-assoc 
        ((((f  g) +₁ (extend (now  (f  g))))  (idC +₁ τ (U , V)))  distributeˡ⁻¹)  (idC  out)      ≈⟨ (+₁∘+₁ ⟩∘⟨refl) ⟩∘⟨refl 
        ((((f  g)  idC) +₁ (extend (now  (f  g))  τ (U , V)))  distributeˡ⁻¹)  (idC  out)         ≈⟨ sym (((+₁-cong₂ id-comm-sym identityʳ) ⟩∘⟨refl) ⟩∘⟨refl) 
        (((idC  (f  g)) +₁ ((extend (now  (f  g))  τ (U , V))  idC))  distributeˡ⁻¹)  (idC  out) ≈⟨ sym (pullˡ (pullˡ +₁∘+₁)) 
        (idC +₁ (extend (now  (f  g))  τ (U , V)))  (((f  g) +₁ idC)  distributeˡ⁻¹)  (idC  out)  

  Strength.identityˡ strength {X} = by-coinduction ((π₂ +₁ idC)  distributeˡ⁻¹  (idC  out)) coind₁ coind₂
    where
    open Terminal terminal using ()
    coind₁ : out  extend (now  π₂)  τ ( , X)  (idC +₁ extend (now  π₂)  τ ( , X))  (π₂ +₁ idC)  distributeˡ⁻¹  (idC  out)
    coind₁ = begin 
      out  extend (now  π₂)  τ ( , X)                                                                                                 ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (sym identityʳ))  
      out  extend (now  π₂)  τ ( , X)  idC                                                                                           ≈⟨ pullˡ (out-law π₂)  
      ((π₂ +₁ extend (now  π₂))  out)  τ ( , X)  idC                                                                                 ≈⟨ pullʳ (pullˡ (τ-law (Terminal.⊤ terminal , X)))  
      (π₂ +₁ extend (now  π₂))  ((idC +₁ τ ( , X))  distributeˡ⁻¹  (idC  out))  idC                                                ≈⟨ refl⟩∘⟨ (pullʳ (assoc  sym helper))  
      (π₂ +₁ extend (now  π₂))  (idC +₁ τ ( , X))  ( Terminal.! terminal , idC  +₁ idC)  (π₂ +₁ idC)  distributeˡ⁻¹  (idC  out) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ (pullˡ (+₁∘+₁  +₁-cong₂ (_≅_.isoˡ ⊤×A≅A) identity²  []-unique ((identity² ⟩∘⟨refl)  id-comm-sym) ((identity² ⟩∘⟨refl)  id-comm-sym)) )  
      (π₂ +₁ extend (now  π₂))  (idC +₁ τ ( , X))  (idC  idC)  distributeˡ⁻¹  (idC  out)                                          ≈⟨ pullˡ +₁∘+₁  
      (π₂  idC +₁ extend (now  π₂)  τ ( , X))  (idC  idC)  distributeˡ⁻¹  (idC  out)                                             ≈⟨ (+₁-cong₂ id-comm refl) ⟩∘⟨refl  
      (idC  π₂ +₁ extend (now  π₂)  τ ( , X))  (idC  idC)  distributeˡ⁻¹  (idC  out)                                             ≈˘⟨ pullˡ +₁∘+₁  
      (idC +₁ extend (now  π₂))  (π₂ +₁ τ ( , X))  (idC  idC)  distributeˡ⁻¹  (idC  out)                                          ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (elimˡ identity²))  
      (idC +₁ extend (now  π₂))  (π₂ +₁ τ ( , X))  distributeˡ⁻¹  (idC  out)                                                        ≈˘⟨ refl⟩∘⟨ ((+₁-cong₂ identityˡ identityʳ) ⟩∘⟨refl)  
      (idC +₁ extend (now  π₂))  (idC  π₂ +₁ τ ( , X)  idC)  distributeˡ⁻¹  (idC  out)                                            ≈˘⟨ pullʳ (pullˡ +₁∘+₁)  
      ((idC +₁ extend (now  π₂))  (idC +₁ τ ( , X)))  (π₂ +₁ idC)  distributeˡ⁻¹  (idC  out)                                       ≈˘⟨ (homomorphism (X +-)) ⟩∘⟨refl  
      (idC +₁ extend (now  π₂)  τ ( , X))  (π₂ +₁ idC)  distributeˡ⁻¹  (idC  out)                                                  
      where
        helper : ( Terminal.! terminal , idC  +₁ idC)  (π₂ +₁ idC)  distributeˡ⁻¹  (idC  out)  distributeˡ⁻¹ {Terminal.⊤ terminal} {X} {D₀ X}  (idC  out)  idC
        helper = begin 
          ( Terminal.! terminal , idC  +₁ idC)  (π₂ +₁ idC)  distributeˡ⁻¹  (idC  out) ≈⟨ pullˡ +₁∘+₁  
          ( Terminal.! terminal , idC   π₂ +₁ idC  idC)  distributeˡ⁻¹  (idC  out)    ≈⟨ +₁-cong₂ (_≅_.isoˡ ⊤×A≅A) identity² ⟩∘⟨ (refl⟩∘⟨ sym identityʳ)  
          (idC +₁ idC)  distributeˡ⁻¹  (idC  out)  idC                                   ≈⟨ elimˡ ([]-unique id-comm-sym id-comm-sym)  
          distributeˡ⁻¹  (idC  out)  idC                                                  
    coind₂ : out  π₂  (idC +₁ π₂)  (π₂ +₁ idC)  distributeˡ⁻¹  (idC  out)
    coind₂ = begin 
      out  π₂                                                ≈˘⟨ π₂∘⁂  
      π₂  (idC  out)                                        ≈˘⟨ pullˡ distributeˡ⁻¹-π₂ 
      (π₂ +₁ π₂)  distributeˡ⁻¹  (idC  out)                ≈˘⟨ (+₁-cong₂ identityˡ identityʳ) ⟩∘⟨refl  
      (idC  π₂ +₁ π₂  idC)  distributeˡ⁻¹  (idC  out)    ≈˘⟨ pullˡ +₁∘+₁  
      (idC +₁ π₂)  (π₂ +₁ idC)  distributeˡ⁻¹  (idC  out) 

  Strength.η-comm strength {X} {Y} = τ-now (X , Y)

  Strength.μ-η-comm strength {X} {Y} = by-coinduction ([ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹  (idC  out)) coind₁ coind₂
    where
    -- diagram: https://q.uiver.app/#q=WzAsNyxbMCwwLCJYXFx0aW1lcyBERFkiXSxbMiwwLCJEKFhcXHRpbWVzIERZKSJdLFs0LDAsIkREKFhcXHRpbWVzIFkpIl0sWzAsMiwiWFxcdGltZXMgKERZK0REWSkiXSxbMiwyLCJYXFx0aW1lcyBEWSsgWFxcdGltZXMgRERZIl0sWzQsMiwiWFxcdGltZXMgWSsgREQoWFxcdGltZXMgWSkiXSxbMCw0LCJYXFx0aW1lcyBZKyBYXFx0aW1lcyBERFkiXSxbMCwzLCJpZFxcdGltZXMgb3V0IiwyXSxbMCwxLCJcXHRhdSJdLFsxLDIsIlxcdGF1XioiXSxbMyw0LCIoaWQrXFx0YXUpZGlzdCJdLFs0LDUsIltvdXRcXHRhdSxpbnJcXHRhdV4qXSJdLFsyLDUsIm91dCJdLFsxLDRdLFs2LDUsImlkK1xcdGF1XipcXHRhdSIsMl0sWzMsNiwiWyhpZCArIGlkXFx0aW1lcyBub3cpZGlzdCAoaWRcXHRpbWVzIG91dCksaW5yXWRpc3QiLDJdXQ==
    id*∘Dτ : extend idC  extend (now  τ (X , Y))  extend (τ (X , Y))
    id*∘Dτ = begin 
      extend idC  extend (now  τ (X , Y)) ≈⟨ sym k-assoc  
      extend (extend idC  now  τ (X , Y)) ≈⟨ extend-≈ (pullˡ k-identityʳ) 
      extend (idC  τ (X , Y))              ≈⟨ extend-≈ identityˡ  
      extend (τ (X , Y))                    
    coind₁ : out  extend idC  extend (now  τ (X , Y))  τ (X , D₀ Y)  (idC +₁ (extend idC  extend (now  τ (X , Y))  τ (X , D₀ Y)))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹  (idC  out)
    coind₁ = begin 
      out  extend idC  extend (now  τ (X , Y))  τ (X , D₀ Y)                                                                                                  ≈⟨ refl⟩∘⟨ (pullˡ id*∘Dτ) 
      out  extend (τ (X , Y))  τ (X , D₀ Y)                                                                                                                     ≈⟨ square 
      [ out  τ (X , Y) , i₂  extend (τ (X , Y)) ]  (idC +₁ τ (X , D₀ Y))  distributeˡ⁻¹  (idC  out)                                                         ≈⟨ sym-assoc  sym-assoc  (assoc  tri) ⟩∘⟨refl 
      ((idC +₁ extend (τ (X , Y))  τ (X , D₀ Y))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹)  (idC  out)                    ≈⟨ assoc  refl⟩∘⟨ assoc 
      (idC +₁ (extend (τ (X , Y))  τ (X , D₀ Y)))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹  (idC  out)                    ≈⟨ (+₁-cong₂ refl (sym (pullˡ id*∘Dτ))) ⟩∘⟨refl 
      (idC +₁ (extend idC  extend (now  τ (X , Y))  τ (X , D₀ Y)))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹  (idC  out) 
      where
      tri : [ out  τ (X , Y) , i₂  extend (τ (X , Y)) ]  (idC +₁ τ (X , D₀ Y))  distributeˡ⁻¹  (idC +₁ extend (τ (X , Y))  τ (X , D₀ Y))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹
      tri = begin 
        [ out  τ (X , Y) , i₂  extend (τ (X , Y)) ]  (idC +₁ τ (X , D₀ Y))  distributeˡ⁻¹                                                                                 ≈⟨ pullˡ []∘+₁  
        [ (out  τ (X , Y))  idC , (i₂  extend (τ (X , Y)))  τ (X , D₀ Y) ]  distributeˡ⁻¹                                                                                ≈⟨ ([]-cong₂ (identityʳ  τ-law (X , Y)) assoc) ⟩∘⟨refl  
        [ (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  out) , i₂  extend (τ (X , Y))  τ (X , D₀ Y) ]  distributeˡ⁻¹                                                         ≈⟨ sym (([]-cong₂ ((+₁-cong₂ refl k-identityʳ) ⟩∘⟨refl) refl) ⟩∘⟨refl)  
        [ (idC +₁ extend (τ (X , Y))  now)  distributeˡ⁻¹  (idC  out) , i₂  extend (τ (X , Y))  τ (X , D₀ Y) ]  distributeˡ⁻¹                                          ≈⟨ sym (([]-cong₂ ((+₁-cong₂ identity² (pullʳ (τ-now (X , D₀ Y)))) ⟩∘⟨refl) refl) ⟩∘⟨refl)  
        [ (idC  idC +₁ (extend (τ (X , Y))  τ (X , D₀ Y))  (idC  now))  distributeˡ⁻¹  (idC  out) , i₂  extend (τ (X , Y))  τ (X , D₀ Y) ]  distributeˡ⁻¹           ≈⟨ sym (([]-cong₂ (pullˡ +₁∘+₁) +₁∘i₂) ⟩∘⟨refl)  
        [ (idC +₁ extend (τ (X , Y))  τ (X , D₀ Y))  (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , (idC +₁ extend (τ (X , Y))  τ (X , D₀ Y))  i₂ ]  distributeˡ⁻¹ ≈⟨ sym (pullˡ ∘[])  
        (idC +₁ extend (τ (X , Y))  τ (X , D₀ Y))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹                                              
      square : out  extend (τ (X , Y))  τ (X , D₀ Y)  [ out  τ (X , Y) , i₂  extend (τ (X , Y)) ]  (idC +₁ τ (X , D₀ Y))  distributeˡ⁻¹  (idC  out)
      square = begin 
        out  extend (τ (X , Y))  τ (X , D₀ Y)                                                             ≈⟨ pullˡ (extendlaw (τ (X , Y)))  
        ([ out  τ (X , Y) , i₂  extend (τ (X , Y)) ]  out)  τ (X , D₀ Y)                                ≈⟨ pullʳ (τ-law _)  
        [ out  τ (X , Y) , i₂  extend (τ (X , Y)) ]  (idC +₁ τ (X , D₀ Y))  distributeˡ⁻¹  (idC  out) 
    coind₂ : out  τ (X , Y)  (idC  extend idC)  (idC +₁ τ (X , Y)  (idC  extend idC))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹  (idC  out)
    coind₂ = begin 
      out  τ (X , Y)  (idC  extend idC)                                                                                                  ≈⟨ pullˡ (τ-law (X , Y))  
      ((idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  out))  (idC  extend idC)                                                               ≈⟨ pullʳ (pullʳ (⁂∘⁂  ⁂-cong₂ identity² refl)) 
      (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  out  extend idC)                                                                         ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ⁂-cong₂ refl (extendlaw idC) 
      (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  [ out  idC , i₂  extend idC ]  out)                                                    ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ⁂-cong₂ refl (([]-cong₂ identityʳ refl) ⟩∘⟨refl) 
      (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  [ out , i₂  extend idC ]  out)                                                          ≈⟨ refl⟩∘⟨ refl⟩∘⟨ sym (⁂∘⁂  ⁂-cong₂ identity² refl) 
      (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  [ out , i₂  extend idC ])  (idC  out)                                                  ≈⟨ sym-assoc  pullˡ (assoc  tri₂) 
      ((idC +₁ τ (X , Y)  (idC  extend idC))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹)  (idC  out) ≈⟨ assoc  refl⟩∘⟨ assoc 
      (idC +₁ τ (X , Y)  (idC  extend idC))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹  (idC  out)   
      where
        tri₂' : (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  [ out , i₂  extend idC ])  [ (idC  i₁) , (idC  i₂) ]  (idC +₁ τ (X , Y)  (idC  extend idC))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹  distributeˡ
        tri₂' = begin 
          (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  [ out , i₂  extend idC ])  [ (idC  i₁) , (idC  i₂) ]                                            ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ ∘[])  
          (idC +₁ τ (X , Y))  distributeˡ⁻¹  [ (idC  [ out , i₂  extend idC ])  (idC  i₁) , (idC  [ out , i₂  extend idC ])  (idC  i₂) ]        ≈⟨ refl⟩∘⟨ refl⟩∘⟨ []-cong₂ ⁂∘⁂ ⁂∘⁂ 
          (idC +₁ τ (X , Y))  distributeˡ⁻¹  [ (idC  idC  [ out , i₂  extend idC ]  i₁) , (idC  idC  [ out , i₂  extend idC ]  i₂) ]            ≈⟨ refl⟩∘⟨ refl⟩∘⟨ []-cong₂ (⁂-cong₂ identity² inject₁) (⁂-cong₂ identity² inject₂) 
          (idC +₁ τ (X , Y))  distributeˡ⁻¹  [ idC  out , idC  i₂  extend idC ]                                                                      ≈⟨ refl⟩∘⟨ ∘[] 
          (idC +₁ τ (X , Y))  [ distributeˡ⁻¹  (idC  out) , distributeˡ⁻¹  (idC  i₂  extend idC) ]                                                  ≈⟨ ∘[] 
          [ (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  out) , (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  i₂  extend idC) ]                             ≈⟨ sym ([]-cong₂ refl (pullʳ (pullʳ (⁂∘⁂  ⁂-cong₂ identity² refl)))) 
          [ (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  out) , ((idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  i₂))  (idC  extend idC) ]                   ≈⟨ []-cong₂ refl ((refl⟩∘⟨ distributeˡ⁻¹-i₂) ⟩∘⟨refl) 
          [ (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  out) , ((idC +₁ τ (X , Y))  i₂)  (idC  extend idC) ]                                           ≈⟨ []-cong₂ refl (pushˡ +₁∘i₂) 
          [ (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  out) , i₂  τ (X , Y)  (idC  extend idC) ]                                                      ≈⟨ []-cong₂ ((+₁-cong₂ refl (introʳ (⟨⟩-unique id-comm (id-comm  (sym k-identityʳ) ⟩∘⟨refl)))) ⟩∘⟨refl) refl 
          [ (idC +₁ τ (X , Y)  (idC  extend idC  now))  distributeˡ⁻¹  (idC  out) , i₂  τ (X , Y)  (idC  extend idC) ]                           ≈⟨ []-cong₂ ((sym (+₁-cong₂ refl (refl⟩∘⟨ (⁂∘⁂  ⁂-cong₂ identity² refl)))) ⟩∘⟨refl) refl 
          [ (idC +₁ τ (X , Y)  (idC  extend idC)  (idC  now))  distributeˡ⁻¹  (idC  out) , i₂  τ (X , Y)  (idC  extend idC) ]                   ≈⟨ sym ([]-cong₂ (pullˡ (+₁∘+₁  +₁-cong₂ identity² assoc)) +₁∘i₂) 
          [ (idC +₁ τ (X , Y)  (idC  extend idC))  (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , (idC +₁ τ (X , Y)  (idC  extend idC))  i₂ ] ≈⟨ sym ∘[] 
          (idC +₁ τ (X , Y)  (idC  extend idC))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]                                           ≈⟨ sym (refl⟩∘⟨ (elimʳ (IsIso.isoˡ isIsoˡ))) 
          (idC +₁ τ (X , Y)  (idC  extend idC))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹  distributeˡ             
        tri₂ : (idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  [ out , i₂  extend idC ])  (idC +₁ τ (X , Y)  (idC  extend idC))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹
        tri₂ = Iso⇒Epi
          (IsIso.iso isIsoˡ)
          ((idC +₁ τ (X , Y))  distributeˡ⁻¹  (idC  [ out , i₂  extend idC ])) 
          ((idC +₁ τ (X , Y)  (idC  extend idC))  [ (idC +₁ (idC  now))  distributeˡ⁻¹  (idC  out) , i₂ ]  distributeˡ⁻¹) 
          (assoc  refl⟩∘⟨ assoc  tri₂'  sym-assoc  sym-assoc  assoc ⟩∘⟨refl)

  Strength.strength-assoc strength {X} {Y} {Z} = by-coinduction (( π₁  π₁ ,  π₂  π₁ , π₂   +₁ idC)  distributeˡ⁻¹  (idC  out)) coind₁ coind₂
    where
    coind₁ : out  extend (now   π₁  π₁ ,  π₂  π₁ , π₂  )  τ (X × Y , Z)  (idC +₁ extend (now   π₁  π₁ ,  π₂  π₁ , π₂  )  τ (X × Y , Z))  ( π₁  π₁ ,  π₂  π₁ , π₂   +₁ idC)  distributeˡ⁻¹  (idC  out)
    coind₁ = begin 
      out  extend (now   π₁  π₁ ,  π₂  π₁ , π₂  )  τ (X × Y , Z)                                                                                        ≈⟨ pullˡ (extendlaw (now   π₁  π₁ ,  π₂  π₁ , π₂  ))  
      ([ out  now   π₁  π₁ ,  π₂  π₁ , π₂   , i₂  extend (now   π₁  π₁ ,  π₂  π₁ , π₂  ) ]  out)  τ (X × Y , Z)                                ≈⟨ pullʳ (τ-law (X × Y , Z))  
      [ out  now   π₁  π₁ ,  π₂  π₁ , π₂   , i₂  extend (now   π₁  π₁ ,  π₂  π₁ , π₂  ) ]  (idC +₁ τ (X × Y , Z))  distributeˡ⁻¹  (idC  out) ≈⟨ ([]-cong₂ (pullˡ unitlaw) refl) ⟩∘⟨refl  
      ( π₁  π₁ ,  π₂  π₁ , π₂   +₁ extend (now   π₁  π₁ ,  π₂  π₁ , π₂  ))  (idC +₁ τ (X × Y , Z))  distributeˡ⁻¹  (idC  out)                   ≈⟨ pullˡ +₁∘+₁  
      ( π₁  π₁ ,  π₂  π₁ , π₂    idC +₁ extend (now   π₁  π₁ ,  π₂  π₁ , π₂  )  τ (X × Y , Z))  distributeˡ⁻¹  (idC  out)                      ≈⟨ (+₁-cong₂ id-comm (sym identityʳ)) ⟩∘⟨refl  
      (idC   π₁  π₁ ,  π₂  π₁ , π₂   +₁ (extend (now   π₁  π₁ ,  π₂  π₁ , π₂  )  τ (X × Y , Z))  idC)  distributeˡ⁻¹  (idC  out)              ≈⟨ sym (pullˡ +₁∘+₁)  
      (idC +₁ extend (now   π₁  π₁ ,  π₂  π₁ , π₂  )  τ (X × Y , Z))  ( π₁  π₁ ,  π₂  π₁ , π₂   +₁ idC)  distributeˡ⁻¹  (idC  out)             
    coind₂ : out  τ (X , Y × Z)  (idC  τ (Y , Z))   π₁  π₁ ,  π₂  π₁ , π₂    (idC +₁ τ (X , Y × Z)  (idC  τ (Y , Z))   π₁  π₁ ,  π₂  π₁ , π₂  )  ( π₁  π₁ ,  π₂  π₁ , π₂   +₁ idC)  distributeˡ⁻¹  (idC  out)
    coind₂ = begin 
      out  τ (X , Y × Z)  (idC  τ (Y , Z))   π₁  π₁ ,  π₂  π₁ , π₂                                                                                ≈⟨ pullˡ (τ-law (X , Y × Z))  
      ((idC +₁ τ (X , Y × Z))  distributeˡ⁻¹  (idC  out))  (idC  τ (Y , Z))   π₁  π₁ ,  π₂  π₁ , π₂                                             ≈⟨ pullʳ (pullˡ (pullʳ ⁂∘⁂))  
      (idC +₁ τ (X , Y × Z))  (distributeˡ⁻¹  (idC  idC  out  τ (Y , Z)))   π₁  π₁ ,  π₂  π₁ , π₂                                               ≈⟨ refl⟩∘⟨ assoc  
      (idC +₁ τ (X , Y × Z))  distributeˡ⁻¹  (idC  idC  out  τ (Y , Z))   π₁  π₁ ,  π₂  π₁ , π₂                                                 ≈˘⟨ refl⟩∘⟨ (refl⟩∘⟨ (⁂-cong₂ identityʳ (assoc  sym (τ-law (Y , Z)))) ⟩∘⟨refl)  
      (idC +₁ τ (X , Y × Z))  distributeˡ⁻¹  ((idC  idC)  idC  ((idC +₁ τ (Y , Z))  distributeˡ⁻¹)  (idC  out))   π₁  π₁ ,  π₂  π₁ , π₂      ≈⟨ sym (refl⟩∘⟨ (pullʳ (pullˡ ⁂∘⁂  pullˡ ⁂∘⁂)))  
      (idC +₁ τ (X , Y × Z))  (distributeˡ⁻¹  (idC  (idC +₁ τ (Y , Z))))  (idC  distributeˡ⁻¹)  (idC  (idC  out))   π₁  π₁ ,  π₂  π₁ , π₂    ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (refl⟩∘⟨ helper₁))  
      (idC +₁ τ (X , Y × Z))  (distributeˡ⁻¹  (idC  (idC +₁ τ (Y , Z))))  (idC  distributeˡ⁻¹)   π₁  π₁ ,  π₂  π₁ , π₂    (idC  out)          ≈⟨ refl⟩∘⟨ (helper₂ ⟩∘⟨refl)  
      (idC +₁ τ (X , Y × Z))  ((idC +₁ (idC  τ (Y , Z)))  distributeˡ⁻¹)  (idC  distributeˡ⁻¹)   π₁  π₁ ,  π₂  π₁ , π₂    (idC  out)          ≈⟨ refl⟩∘⟨ (assoc  refl⟩∘⟨ sym assoc²') 
      (idC +₁ τ (X , Y × Z))  (idC +₁ (idC  τ (Y , Z)))  (distributeˡ⁻¹  (idC  distributeˡ⁻¹)   π₁  π₁ ,  π₂  π₁ , π₂  )  (idC  out)          ≈⟨ pullˡ (+₁∘+₁  +₁-cong₂ identity² refl)  
      (idC +₁ τ (X , Y × Z)  (idC  τ (Y , Z)))  (distributeˡ⁻¹  (idC  distributeˡ⁻¹)   π₁  π₁ ,  π₂  π₁ , π₂  )  (idC  out)                   ≈⟨ refl⟩∘⟨ (helper₃ ⟩∘⟨refl)  
      (idC +₁ τ (X , Y × Z)  (idC  τ (Y , Z)))  (( π₁  π₁ ,  π₂  π₁ , π₂   +₁  π₁  π₁ ,  π₂  π₁ , π₂  )  distributeˡ⁻¹)  (idC  out)       ≈⟨ assoc²'' 
      ((idC +₁ τ (X , Y × Z)  (idC  τ (Y , Z)))  ( π₁  π₁ ,  π₂  π₁ , π₂   +₁  π₁  π₁ ,  π₂  π₁ , π₂  ))  distributeˡ⁻¹  (idC  out)       ≈⟨ sym ((+₁-cong₂ refl (identityʳ  sym-assoc)  sym +₁∘+₁) ⟩∘⟨refl)  
      (idC   π₁  π₁ ,  π₂  π₁ , π₂   +₁ (τ (X , Y × Z)  (idC  τ (Y , Z))   π₁  π₁ ,  π₂  π₁ , π₂  )  idC)  distributeˡ⁻¹  (idC  out)    ≈⟨ sym (pullˡ +₁∘+₁)  
      (idC +₁ τ (X , Y × Z)  (idC  τ (Y , Z))   π₁  π₁ ,  π₂  π₁ , π₂  )  ( π₁  π₁ ,  π₂  π₁ , π₂   +₁ idC)  distributeˡ⁻¹  (idC  out)   
      where
      helper₁ : (idC  (idC  out))   π₁  π₁ ,  π₂  π₁ , π₂     π₁  π₁ ,  π₂  π₁ , π₂    (idC {X × Y}  out {Z})
      helper₁ = begin 
        (idC  (idC  out))   π₁  π₁ ,  π₂  π₁ , π₂                                         ≈⟨ ⁂∘⟨⟩  
         idC  π₁  π₁ , (idC  out)   π₂  π₁ , π₂                                           ≈⟨ ⟨⟩-cong₂ identityˡ ⁂∘⟨⟩  
         π₁  π₁ ,  idC  π₂  π₁ , out  π₂                                                   ≈⟨ ⟨⟩-cong₂ refl (⟨⟩-cong₂ identityˡ refl)  
         π₁  π₁ ,  π₂  π₁ , out  π₂                                                         ≈⟨ sym (⟨⟩-cong₂ refl (⟨⟩-cong₂ (refl⟩∘⟨ identityˡ) refl))  
         π₁  π₁ ,  π₂  idC  π₁ , out  π₂                                                   ≈⟨ sym (⟨⟩-cong₂ (refl⟩∘⟨ identityˡ) (⟨⟩-cong₂ (pullʳ π₁∘⁂) π₂∘⁂))  
         π₁  idC  π₁ ,  (π₂  π₁)  (idC {X × Y}  out {Z}) , π₂  (idC {X × Y}  out {Z})   ≈⟨ sym (⟨⟩-cong₂ (pullʳ project₁) ⟨⟩∘)  
         (π₁  π₁)  (idC {X × Y}  out {Z}) ,  π₂  π₁ , π₂   (idC {X × Y}  out {Z})        ≈⟨ sym ⟨⟩∘  
         π₁  π₁ ,  π₂  π₁ , π₂    (idC {X × Y}  out {Z})                                   
      helper₂ : distributeˡ⁻¹  (idC  (idC +₁ τ (Y , Z)))  (idC +₁ (idC  τ (Y , Z)))  distributeˡ⁻¹
      helper₂ = sym (distributeˡ⁻¹-natural idC idC (τ (Y , Z)))  (+₁-cong₂ (⟨⟩-unique id-comm id-comm) refl) ⟩∘⟨refl
      helper₃ : distributeˡ⁻¹  (idC  distributeˡ⁻¹)   π₁  π₁ ,  π₂  π₁ , π₂    ( π₁  π₁ ,  π₂  π₁ , π₂   +₁  π₁  π₁ ,  π₂  π₁ , π₂  )  distributeˡ⁻¹
      helper₃ = sym (begin 
        ( π₁  π₁ ,  π₂  π₁ , π₂   +₁  π₁  π₁ ,  π₂  π₁ , π₂  )  distributeˡ⁻¹                                                                                                                                  ≈⟨ introˡ (IsIso.isoˡ isIsoˡ)  
        (distributeˡ⁻¹  distributeˡ)  ( π₁  π₁ ,  π₂  π₁ , π₂   +₁  π₁  π₁ ,  π₂  π₁ , π₂  )  distributeˡ⁻¹                                                                                                  ≈⟨ pullʳ (pullˡ []∘+₁) 
        distributeˡ⁻¹  [ (idC  i₁)   π₁  π₁ ,  π₂  π₁ , π₂   , (idC  i₂)   π₁  π₁ ,  π₂  π₁ , π₂   ]  distributeˡ⁻¹                                                                                       ≈⟨ refl⟩∘⟨ (([]-cong₂ ⁂∘⟨⟩ ⁂∘⟨⟩) ⟩∘⟨refl) 
        distributeˡ⁻¹  [  idC  π₁  π₁ , i₁   π₂  π₁ , π₂   ,  idC  π₁  π₁ , i₂   π₂  π₁ , π₂   ]  distributeˡ⁻¹                                                                                           ≈⟨ refl⟩∘⟨ []-cong₂ (⟨⟩-cong₂ identityˡ (pushˡ (sym distributeˡ⁻¹-i₁))) (⟨⟩-cong₂ identityˡ ((pushˡ (sym distributeˡ⁻¹-i₂)))) ⟩∘⟨refl 
        distributeˡ⁻¹  [  π₁  π₁ , distributeˡ⁻¹  (idC  i₁)   π₂  π₁ , π₂   ,  π₁  π₁ , distributeˡ⁻¹  (idC  i₂)   π₂  π₁ , π₂   ]  distributeˡ⁻¹                                                       ≈⟨ sym (refl⟩∘⟨ []-cong₂ (⟨⟩-cong₂ refl (refl⟩∘⟨ (⟨⟩-cong₂ (refl⟩∘⟨ identityˡ  sym identityˡ) refl  sym ⁂∘⟨⟩))) (⟨⟩-cong₂ refl (refl⟩∘⟨ (⟨⟩-cong₂ (refl⟩∘⟨ identityˡ  sym identityˡ) refl  sym ⁂∘⟨⟩))) ⟩∘⟨refl) 
        distributeˡ⁻¹  [  π₁  π₁ , distributeˡ⁻¹   π₂  idC  π₁ , i₁  π₂   ,  π₁  π₁ , distributeˡ⁻¹   π₂  idC  π₁ , i₂  π₂   ]  distributeˡ⁻¹                                                           ≈⟨ sym (refl⟩∘⟨ []-cong₂ (⟨⟩-cong₂ (identityˡ  refl⟩∘⟨ identityˡ) (refl⟩∘⟨ (⟨⟩-cong₂ (pullʳ π₁∘⁂) π₂∘⁂))) (⟨⟩-cong₂ (identityˡ  refl⟩∘⟨ identityˡ) (refl⟩∘⟨ (⟨⟩-cong₂ (pullʳ π₁∘⁂) π₂∘⁂))) ⟩∘⟨refl) 
        distributeˡ⁻¹  [  idC  π₁  idC  π₁ , distributeˡ⁻¹   (π₂  π₁)  (idC  i₁) , π₂  (idC  i₁)   ,  idC  π₁  idC  π₁ , distributeˡ⁻¹   (π₂  π₁)  (idC  i₂) , π₂  (idC  i₂)   ]  distributeˡ⁻¹ ≈⟨ sym (refl⟩∘⟨ []-cong₂ (⟨⟩-cong₂ (pullʳ (pullʳ π₁∘⁂)) (pullʳ ⟨⟩∘)) (⟨⟩-cong₂ (pullʳ (pullʳ π₁∘⁂)) (pullʳ ⟨⟩∘)) ⟩∘⟨refl) 
        distributeˡ⁻¹  [  (idC  π₁  π₁)  (idC  i₁) , (distributeˡ⁻¹   π₂  π₁ , π₂ )  (idC  i₁)  ,  (idC  π₁  π₁)  (idC  i₂) , (distributeˡ⁻¹   π₂  π₁ , π₂ )  (idC  i₂)  ]  distributeˡ⁻¹         ≈⟨ sym (refl⟩∘⟨ []-cong₂ ⟨⟩∘ ⟨⟩∘ ⟩∘⟨refl) 
        distributeˡ⁻¹  [ ( idC  π₁  π₁ , distributeˡ⁻¹   π₂  π₁ , π₂    (idC  i₁)) , ( idC  π₁  π₁ , distributeˡ⁻¹   π₂  π₁ , π₂    (idC   i₂)) ]  distributeˡ⁻¹                                      ≈˘⟨ pullʳ (pullˡ ∘[]) 
        (distributeˡ⁻¹   idC  π₁  π₁ , distributeˡ⁻¹   π₂  π₁ , π₂  )  distributeˡ  distributeˡ⁻¹                                                                                                                ≈⟨ sym (introʳ (IsIso.isoʳ isIsoˡ)) 
        distributeˡ⁻¹   idC  π₁  π₁ , distributeˡ⁻¹   π₂  π₁ , π₂                                                                                                                                                  ≈⟨ sym (refl⟩∘⟨ ⁂∘⟨⟩) 
        distributeˡ⁻¹  (idC  distributeˡ⁻¹)   π₁  π₁ ,  π₂  π₁ , π₂                                                                                                                                                )

  strongMonad : StrongMonad monoidal
  strongMonad = record { M = monad ; strength = strength }