open import Level
open import Data.Product using (_,_)
open import Categories.Category
open import Categories.Functor hiding (id)
open import Categories.Functor.Coalgebra
open import Monad.Instance.Delay
open import Categories.Monad.Strong
open import Categories.NaturalTransformation hiding (id)
open import Categories.Object.Terminal
open import Categories.Category.Distributive
import Categories.Morphism as M
import Categories.Morphism.Reasoning as MR
import Categories.Morphism.Properties as MP
module Monad.Instance.Delay.Strong {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 MP C
open MR C
open M C
open DelayM D
open D-Kleisli
open D-Monad
open Coit
module τ-mod where
abstract
τ : ∀ {X Y} → X × D₀ Y ⇒ D₀ (X × Y)
τ {X} {Y} = coit (distributeˡ⁻¹ ∘ (id ⁂ out))
τ-commutes : ∀ {X Y} → out ∘ τ {X} {Y} ≈ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
τ-commutes = coit-commutes (distributeˡ⁻¹ ∘ (id ⁂ out))
τ-out⁻¹ : ∀ {X Y} → τ {X} {Y} ∘ (id ⁂ out⁻¹) ≈ out⁻¹ ∘ (id +₁ τ) ∘ distributeˡ⁻¹
τ-out⁻¹ = begin
τ ∘ (id ⁂ out⁻¹) ≈⟨ introˡ out⁻¹∘out ⟩
(out⁻¹ ∘ out) ∘ τ ∘ (id ⁂ out⁻¹) ≈⟨ pullʳ (pullˡ τ-commutes) ⟩
out⁻¹ ∘ ((id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) ∘ (id ⁂ out⁻¹) ≈⟨ refl⟩∘⟨ (assoc ○ refl⟩∘⟨ assoc) ⟩
out⁻¹ ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∘ (id ⁂ out⁻¹) ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (elimʳ (⁂∘⁂ ○ (⁂-cong₂ identity² out∘out⁻¹) ○ ((⟨⟩-cong₂ identityˡ identityˡ) ○ ⁂-η)))) ⟩
out⁻¹ ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∎
τ-now : ∀ {X Y} → τ {X} {Y} ∘ (id ⁂ now) ≈ now
τ-now = begin
τ ∘ (id ⁂ now) ≈⟨ refl⟩∘⟨ sym (⁂∘⁂ ○ (⁂-cong₂ identity² refl)) ⟩
τ ∘ (id ⁂ out⁻¹) ∘ (id ⁂ i₁) ≈⟨ pullˡ τ-out⁻¹ ⟩
(out⁻¹ ∘ (id +₁ τ) ∘ distributeˡ⁻¹) ∘ (id ⁂ i₁) ≈⟨ pullʳ (pullʳ distributeˡ⁻¹-i₁) ⟩
out⁻¹ ∘ (id +₁ τ) ∘ i₁ ≈⟨ refl⟩∘⟨ +₁∘i₁ ⟩
out⁻¹ ∘ i₁ ∘ id ≈⟨ refl⟩∘⟨ identityʳ ⟩
now ∎
τ-later : ∀ {X} {Y} → τ {X} {Y} ∘ (id ⁂ later) ≈ later ∘ τ
τ-later = begin
τ ∘ (id ⁂ later) ≈⟨ refl⟩∘⟨ (sym (⁂∘⁂ ○ ⁂-cong₂ identity² refl)) ⟩
τ ∘ (id ⁂ out⁻¹) ∘ (id ⁂ i₂) ≈⟨ pullˡ τ-out⁻¹ ⟩
(out⁻¹ ∘ (id +₁ τ) ∘ distributeˡ⁻¹) ∘ (id ⁂ i₂) ≈⟨ pullʳ (pullʳ distributeˡ⁻¹-i₂) ⟩
out⁻¹ ∘ (id +₁ τ) ∘ i₂ ≈⟨ refl⟩∘⟨ +₁∘i₂ ⟩
out⁻¹ ∘ i₂ ∘ τ ≈⟨ sym-assoc ⟩
later ∘ τ ∎
τ-identityˡ : ∀ {X} {Y} → D₁ (π₂ {X} {Y}) ∘ τ ≈ π₂
τ-identityˡ {X} {Y} = by-coinduction {f = D₁ (π₂ {X} {Y}) ∘ τ} {g = π₂} ((π₂ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) coind₁ coind₂
where
coind₁ : out ∘ D₁ (π₂ {X} {Y}) ∘ τ ≈ (id +₁ extend (now ∘ π₂) ∘ τ) ∘ (π₂ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
coind₁ = begin
out ∘ D₁ π₂ ∘ τ ≈⟨ extendʳ (D₁-commutes π₂) ⟩
(π₂ +₁ D₁ π₂) ∘ out ∘ τ ≈⟨ refl⟩∘⟨ τ-commutes ⟩
(π₂ +₁ D₁ π₂) ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ pullˡ (+₁∘+₁ ○ +₁-cong₂ identityʳ refl) ⟩
(π₂ +₁ D₁ π₂ ∘ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈˘⟨ pullˡ (+₁∘+₁ ○ +₁-cong₂ identityˡ identityʳ) ⟩
(id +₁ D₁ π₂ ∘ τ) ∘ (π₂ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∎
coind₂ : out ∘ (π₂ {X} {D₀ Y}) ≈ (id +₁ π₂) ∘ (π₂ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
coind₂ = begin
out ∘ π₂ ≈˘⟨ π₂∘⁂ ⟩
π₂ ∘ (id ⁂ out) ≈˘⟨ pullˡ distributeˡ⁻¹-π₂ ⟩
(π₂ +₁ π₂) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈˘⟨ (+₁-cong₂ identityˡ identityʳ) ⟩∘⟨refl ⟩
(id ∘ π₂ +₁ π₂ ∘ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈˘⟨ pullˡ +₁∘+₁ ⟩
(id +₁ π₂) ∘ (π₂ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∎
τ-unique : ∀ {X Y} → (t : X × D₀ Y ⇒ D₀ (X × Y)) → (out ∘ t ≈ (id +₁ t) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) → τ ≈ t
τ-unique {X} {Y} t t-commutes = coit-unique (distributeˡ⁻¹ ∘ (id ⁂ out)) t t-commutes
τ-natural : ∀ {X Y} {A} {B} (f : X ⇒ A) (g : Y ⇒ B) → τ ∘ (f ⁂ D₁ g) ≈ D₁ (f ⁂ g) ∘ τ
τ-natural f g = by-coinduction (((f ⁂ g +₁ id) ∘ distributeˡ⁻¹) ∘ (id ⁂ out)) coind₁ coind₂
where
coind₁ : out ∘ τ ∘ (f ⁂ extend (now ∘ g)) ≈ (id +₁ (τ ∘ (f ⁂ extend (now ∘ g)))) ∘ ((f ⁂ g +₁ id) ∘ distributeˡ⁻¹) ∘ (id ⁂ out)
coind₁ = begin
out ∘ τ ∘ (f ⁂ extend (now ∘ g)) ≈⟨ pullˡ τ-commutes ⟩
((id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) ∘ (f ⁂ extend (now ∘ g)) ≈⟨ pullʳ (pullʳ ⁂∘⁂) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ∘ f ⁂ out ∘ extend (now ∘ g)) ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (⁂-cong₂ identityˡ (extend-commutes (now ∘ g)))) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (f ⁂ [ out ∘ now ∘ g , i₂ ∘ extend (now ∘ g) ] ∘ out) ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (⁂-cong₂ refl (([]-cong₂ (pullˡ unitlaw) refl) ⟩∘⟨refl))) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (f ⁂ [ i₁ ∘ g , i₂ ∘ extend (now ∘ g) ] ∘ out) ≈⟨ refl⟩∘⟨ (refl⟩∘⟨ (⁂-cong₂ (sym identityʳ) refl)) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (f ∘ id ⁂ (g +₁ extend (now ∘ g)) ∘ out) ≈⟨ sym (pullʳ (pullʳ ⁂∘⁂)) ⟩
((id +₁ τ) ∘ distributeˡ⁻¹ ∘ (f ⁂ (g +₁ extend (now ∘ g)))) ∘ (id ⁂ out) ≈⟨ (refl⟩∘⟨ (sym (distributeˡ⁻¹-natural f g (extend (now ∘ g))))) ⟩∘⟨refl ⟩
((id +₁ τ) ∘ ((f ⁂ g) +₁ (f ⁂ extend (now ∘ g))) ∘ distributeˡ⁻¹) ∘ (id ⁂ out) ≈⟨ (pullˡ +₁∘+₁) ⟩∘⟨refl ⟩
((id ∘ (f ⁂ g) +₁ τ ∘ (f ⁂ extend (now ∘ g))) ∘ distributeˡ⁻¹) ∘ (id ⁂ out) ≈⟨ sym (((+₁-cong₂ refl identityʳ) ⟩∘⟨refl) ⟩∘⟨refl) ⟩
((id ∘ (f ⁂ g) +₁ (τ ∘ (f ⁂ extend (now ∘ g))) ∘ id) ∘ distributeˡ⁻¹) ∘ (id ⁂ out) ≈⟨ sym (pullˡ (pullˡ +₁∘+₁)) ⟩
(id +₁ (τ ∘ (f ⁂ extend (now ∘ g)))) ∘ ((f ⁂ g +₁ id) ∘ distributeˡ⁻¹) ∘ (id ⁂ out) ∎
coind₂ : out ∘ extend (now ∘ (f ⁂ g)) ∘ τ ≈ (id +₁ (extend (now ∘ (f ⁂ g)) ∘ τ)) ∘ (((f ⁂ g) +₁ id) ∘ distributeˡ⁻¹) ∘ (id ⁂ out)
coind₂ = begin
out ∘ extend (now ∘ (f ⁂ g)) ∘ τ ≈⟨ pullˡ (extend-commutes (now ∘ (f ⁂ g))) ⟩
([ out ∘ now ∘ (f ⁂ g) , i₂ ∘ extend (now ∘ (f ⁂ g)) ] ∘ out) ∘ τ ≈⟨ (([]-cong₂ (pullˡ unitlaw) refl) ⟩∘⟨refl) ⟩∘⟨refl ⟩
([ i₁ ∘ (f ⁂ g) , i₂ ∘ extend (now ∘ (f ⁂ g)) ] ∘ out) ∘ τ ≈⟨ pullʳ τ-commutes ⟩
((f ⁂ g) +₁ (extend (now ∘ (f ⁂ g)))) ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ sym-assoc ○ sym-assoc ⟩
((((f ⁂ g) +₁ (extend (now ∘ (f ⁂ g)))) ∘ (id +₁ τ)) ∘ distributeˡ⁻¹) ∘ (id ⁂ out) ≈⟨ (+₁∘+₁ ⟩∘⟨refl) ⟩∘⟨refl ⟩
((((f ⁂ g) ∘ id) +₁ (extend (now ∘ (f ⁂ g)) ∘ τ)) ∘ distributeˡ⁻¹) ∘ (id ⁂ out) ≈⟨ sym (((+₁-cong₂ id-comm-sym identityʳ) ⟩∘⟨refl) ⟩∘⟨refl) ⟩
(((id ∘ (f ⁂ g)) +₁ ((extend (now ∘ (f ⁂ g)) ∘ τ) ∘ id)) ∘ distributeˡ⁻¹) ∘ (id ⁂ out) ≈⟨ sym (pullˡ (pullˡ +₁∘+₁)) ⟩
(id +₁ (extend (now ∘ (f ⁂ g)) ∘ τ)) ∘ (((f ⁂ g) +₁ id) ∘ distributeˡ⁻¹) ∘ (id ⁂ out) ∎
open τ-mod
module D-Strong where
strength : Strength monoidal monad
Strength.strengthen strength = ntHelper (record { η = λ (X , Y) → τ {X} {Y}; commute = λ (f , g) → τ-natural f g })
Strength.identityˡ strength {X} = τ-identityˡ {Terminal.⊤ terminal} {X}
Strength.η-comm strength {X} {Y} = τ-now {X} {Y}
Strength.μ-η-comm strength {X} {Y} = by-coinduction ([ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) coind₁ coind₂
where
id*∘Dτ : extend id ∘ extend (now ∘ τ) ≈ extend τ
id*∘Dτ = begin
extend id ∘ extend (now ∘ τ) ≈⟨ DK.sym-assoc ⟩
extend (extend id ∘ now ∘ τ) ≈⟨ extend-≈ (pullˡ DK.identityʳ) ⟩
extend (id ∘ τ) ≈⟨ extend-≈ identityˡ ⟩
extend τ ∎
coind₁ : out ∘ extend id ∘ extend (now ∘ τ) ∘ τ {X} {D₀ Y} ≈ (id +₁ (extend id ∘ extend (now ∘ τ) ∘ τ)) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
coind₁ = begin
out ∘ extend id ∘ extend (now ∘ τ) ∘ τ ≈⟨ refl⟩∘⟨ (pullˡ id*∘Dτ) ⟩
out ∘ extend τ ∘ τ ≈⟨ square ⟩
[ out ∘ τ , i₂ ∘ extend τ ] ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ assoc²εβ ○ ∘-resp-≈ˡ tri ○ assoc²βε ⟩
(id +₁ (extend τ ∘ τ)) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ (+₁-cong₂ refl (sym (pullˡ id*∘Dτ))) ⟩∘⟨refl ⟩
(id +₁ (extend id ∘ extend (now ∘ τ) ∘ τ)) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∎
where
tri : [ out ∘ τ , i₂ ∘ extend τ ] ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ≈ (id +₁ extend τ ∘ τ) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹
tri = begin
[ out ∘ τ , i₂ ∘ extend τ ] ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ≈⟨ pullˡ []∘+₁ ⟩
[ (out ∘ τ) ∘ id , (i₂ ∘ extend τ) ∘ τ ] ∘ distributeˡ⁻¹ ≈⟨ ([]-cong₂ (identityʳ ○ τ-commutes) assoc) ⟩∘⟨refl ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ extend τ ∘ τ ] ∘ distributeˡ⁻¹ ≈˘⟨ ([]-cong₂ ((+₁-cong₂ refl DK.identityʳ) ⟩∘⟨refl) refl) ⟩∘⟨refl ⟩
[ (id +₁ extend τ ∘ now) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ extend τ ∘ τ ] ∘ distributeˡ⁻¹ ≈˘⟨ ([]-cong₂ ((+₁-cong₂ identity² (pullʳ (τ-now))) ⟩∘⟨refl) refl) ⟩∘⟨refl ⟩
[ (id ∘ id +₁ (extend τ ∘ τ) ∘ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ extend τ ∘ τ ] ∘ distributeˡ⁻¹ ≈˘⟨ ([]-cong₂ (pullˡ +₁∘+₁) +₁∘i₂) ⟩∘⟨refl ⟩
[ (id +₁ extend τ ∘ τ) ∘ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , (id +₁ extend τ ∘ τ) ∘ i₂ ] ∘ distributeˡ⁻¹ ≈˘⟨ pullˡ ∘[] ⟩
(id +₁ extend τ ∘ τ) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∎
square : out ∘ extend τ ∘ τ ≈ [ out ∘ τ , i₂ ∘ extend τ ] ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
square = begin
out ∘ extend τ ∘ τ ≈⟨ pullˡ (extend-commutes τ) ⟩
([ out ∘ τ , i₂ ∘ extend τ ] ∘ out) ∘ τ ≈⟨ pullʳ τ-commutes ⟩
[ out ∘ τ , i₂ ∘ extend τ ] ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∎
coind₂ : out ∘ τ {X} {Y} ∘ (id ⁂ extend id) ≈ (id +₁ τ ∘ (id ⁂ extend id)) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
coind₂ = begin
out ∘ τ ∘ (id ⁂ extend id) ≈⟨ pullˡ τ-commutes ⟩
((id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) ∘ (id ⁂ extend id) ≈⟨ pullʳ (pullʳ (⁂∘⁂ ○ ⁂-cong₂ identity² refl)) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out ∘ extend id) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ⁂-cong₂ refl (extend-commutes id) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ [ out ∘ id , i₂ ∘ extend id ] ∘ out) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ⁂-cong₂ refl (([]-cong₂ identityʳ refl) ⟩∘⟨refl) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ [ out , i₂ ∘ extend id ] ∘ out) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ sym (⁂∘⁂ ○ ⁂-cong₂ identity² refl) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ [ out , i₂ ∘ extend id ]) ∘ (id ⁂ out) ≈⟨ sym-assoc ○ pullˡ (assoc ○ Iso⇒Epi (IsIso.iso isIsoˡ) _ _ (assoc²βε ○ epi-helper ○ assoc²εβ)) ○ assoc²βε ⟩
(id +₁ τ ∘ (id ⁂ extend id)) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∎
where
epi-helper : (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ [ out , i₂ ∘ extend id ]) ∘ [ (id ⁂ i₁) , (id ⁂ i₂) ] ≈ (id +₁ τ ∘ (id ⁂ extend id)) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∘ distributeˡ
epi-helper = begin
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ [ out , i₂ ∘ extend id ]) ∘ [ (id ⁂ i₁) , (id ⁂ i₂) ] ≈⟨ refl⟩∘⟨ refl⟩∘⟨ (∘[] ○ []-cong₂ (⁂∘⁂ ○ ⁂-cong₂ identity² inject₁) (⁂∘⁂ ○ ⁂-cong₂ identity² inject₂)) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ [ id ⁂ out , id ⁂ i₂ ∘ extend id ] ≈⟨ ∘-resp-≈ʳ ∘[] ○ ∘[] ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ i₂ ∘ extend id) ] ≈˘⟨ []-cong₂ refl (pullʳ (pullʳ (⁂∘⁂ ○ ⁂-cong₂ identity² refl))) ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , ((id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ i₂)) ∘ (id ⁂ extend id) ] ≈⟨ []-cong₂ refl ((refl⟩∘⟨ distributeˡ⁻¹-i₂) ⟩∘⟨refl) ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , ((id +₁ τ) ∘ i₂) ∘ (id ⁂ extend id) ] ≈⟨ []-cong₂ refl (pushˡ +₁∘i₂) ⟩
[ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ τ ∘ (id ⁂ extend id) ] ≈⟨ []-cong₂ ((+₁-cong₂ refl (introʳ (⟨⟩-unique id-comm (id-comm ○ (sym DK.identityʳ) ⟩∘⟨refl)))) ⟩∘⟨refl) refl ⟩
[ (id +₁ τ ∘ (id ⁂ extend id ∘ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ τ ∘ (id ⁂ extend id) ] ≈⟨ []-cong₂ ((sym (+₁-cong₂ refl (refl⟩∘⟨ (⁂∘⁂ ○ ⁂-cong₂ identity² refl)))) ⟩∘⟨refl) refl ⟩
[ (id +₁ τ ∘ (id ⁂ extend id) ∘ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ∘ τ ∘ (id ⁂ extend id) ] ≈˘⟨ ∘[] ○ []-cong₂ (pullˡ (+₁∘+₁ ○ +₁-cong₂ identity² assoc)) +₁∘i₂ ⟩
(id +₁ τ ∘ (id ⁂ extend id)) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ≈˘⟨ refl⟩∘⟨ (elimʳ (IsIso.isoˡ isIsoˡ)) ⟩
(id +₁ τ ∘ (id ⁂ extend id)) ∘ [ (id +₁ (id ⁂ now)) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) , i₂ ] ∘ distributeˡ⁻¹ ∘ distributeˡ ∎
Strength.strength-assoc strength {X} {Y} {Z} = by-coinduction ((⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) coind₁ coind₂
where
coind₁ : out ∘ extend (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ τ {X × Y} {Z} ≈ (id +₁ extend (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ τ) ∘ (⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
coind₁ = begin
out ∘ extend (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ τ ≈⟨ pullˡ (extend-commutes (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩)) ⟩
([ out ∘ now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ , i₂ ∘ extend (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ] ∘ out) ∘ τ ≈⟨ pullʳ τ-commutes ⟩
[ out ∘ now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ , i₂ ∘ extend (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ] ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ ([]-cong₂ (pullˡ unitlaw) refl) ⟩∘⟨refl ⟩
(⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ extend (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩)) ∘ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈⟨ pullˡ (+₁∘+₁ ○ +₁-cong₂ id-comm (sym identityʳ)) ⟩
(id ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ (extend (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ τ) ∘ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈˘⟨ pullˡ +₁∘+₁ ⟩
(id +₁ extend (now ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ τ) ∘ (⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∎
coind₂ : out ∘ τ {X} {Y × Z} ∘ (id ⁂ τ) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈ (id +₁ τ ∘ (id ⁂ τ) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ (⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)
coind₂ = begin
out ∘ τ ∘ (id ⁂ τ) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈⟨ pullˡ τ-commutes ⟩
((id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) ∘ (id ⁂ τ) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈⟨ pullʳ (pullˡ (pullʳ (⁂∘⁂ ○ ⁂-cong₂ identity² τ-commutes))) ○ ∘-resp-≈ʳ assoc ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ (id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ out)) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (pullˡ (⁂∘⁂ ○ ⁂-cong₂ identity² assoc)) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ (id +₁ τ) ∘ distributeˡ⁻¹) ∘ (id ⁂ (id ⁂ out)) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ refl⟩∘⟨ helper₁ ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ (id +₁ τ) ∘ distributeˡ⁻¹) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ∘ (id ⁂ out) ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (pullˡ (⁂∘⁂ ○ ⁂-cong₂ identity² refl)) ⟩
(id +₁ τ) ∘ distributeˡ⁻¹ ∘ (id ⁂ (id +₁ τ)) ∘ (id ⁂ distributeˡ⁻¹) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ∘ (id ⁂ out) ≈⟨ refl⟩∘⟨ extendʳ (sym (distributeˡ⁻¹-natural id id τ) ○ ∘-resp-≈ˡ (+₁-cong₂ (⟨⟩-unique id-comm id-comm) refl)) ⟩
(id +₁ τ) ∘ (id +₁ (id ⁂ τ)) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ∘ (id ⁂ out) ≈⟨ pullˡ (+₁∘+₁ ○ +₁-cong₂ identity² refl) ⟩
(id +₁ τ ∘ (id ⁂ τ)) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ∘ (id ⁂ out) ≈⟨ refl⟩∘⟨ (assoc²εβ ○ ∘-resp-≈ˡ helper₃ ○ assoc) ⟩
(id +₁ τ ∘ (id ⁂ τ)) ∘ (⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ≈˘⟨ extendʳ (+₁∘+₁ ○ +₁-cong₂ refl (identityʳ ○ sym-assoc) ○ sym +₁∘+₁) ⟩
(id +₁ τ ∘ (id ⁂ τ) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ (⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ out) ∎
where
helper₁ : (id ⁂ (id ⁂ out)) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ∘ (id {X × Y} ⁂ out {Z})
helper₁ = begin
(id ⁂ (id ⁂ out)) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈⟨ ⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityˡ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityˡ refl) ⟩
⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , out ∘ π₂ ⟩ ⟩ ≈˘⟨ ⟨⟩∘ ○ ⟨⟩-cong₂ (pullʳ project₁ ○ ∘-resp-≈ʳ identityˡ) (⟨⟩∘ ○ ⟨⟩-cong₂ (pullʳ π₁∘⁂ ○ ∘-resp-≈ʳ identityˡ) π₂∘⁂) ⟩
⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ∘ (id {X × Y} ⁂ out {Z}) ∎
helper₃ : distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈ (⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ distributeˡ⁻¹
helper₃ = Iso⇒Mono (IsIso.iso isIsoˡ) (distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ((⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ distributeˡ⁻¹) (begin
distributeˡ ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈⟨ cancelˡ (IsIso.isoʳ isIsoˡ) ⟩
(id ⁂ distributeˡ⁻¹) ∘ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈⟨ ⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityˡ refl ⟩
⟨ π₁ ∘ π₁ , distributeˡ⁻¹ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ≈⟨ ⟨⟩-unique unique₁ unique₂ ⟩
[ ⟨ π₁ ∘ π₁ , i₁ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ , ⟨ π₁ ∘ π₁ , i₂ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ] ∘ distributeˡ⁻¹ ≈˘⟨ pullˡ ([]∘+₁ ○ []-cong₂ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityˡ refl) (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityˡ refl)) ⟩
distributeˡ ∘ (⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ +₁ ⟨ π₁ ∘ π₁ , ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩) ∘ distributeˡ⁻¹ ∎)
where
unique₁ : π₁ ∘ [ ⟨ π₁ ∘ π₁ , i₁ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ , ⟨ π₁ ∘ π₁ , i₂ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ] ∘ distributeˡ⁻¹ ≈ π₁ ∘ π₁
unique₁ = begin
π₁ ∘ [ ⟨ π₁ ∘ π₁ , i₁ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ , ⟨ π₁ ∘ π₁ , i₂ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ] ∘ distributeˡ⁻¹ ≈⟨ extendʳ (∘[] ○ []-cong₂ project₁ project₁ ○ sym ∘[]) ⟩
π₁ ∘ [ π₁ , π₁ ] ∘ distributeˡ⁻¹ ≈⟨ refl⟩∘⟨ distributeˡ⁻¹-π₁ ⟩
π₁ ∘ π₁ ∎
unique₂ : π₂ ∘ [ ⟨ π₁ ∘ π₁ , i₁ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ , ⟨ π₁ ∘ π₁ , i₂ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ] ∘ distributeˡ⁻¹ ≈ distributeˡ⁻¹ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩
unique₂ = begin
π₂ ∘ [ ⟨ π₁ ∘ π₁ , i₁ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ , ⟨ π₁ ∘ π₁ , i₂ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ⟩ ] ∘ distributeˡ⁻¹ ≈⟨ pullˡ (∘[] ○ []-cong₂ project₂ project₂) ⟩
(⟨ π₂ ∘ π₁ , π₂ ⟩ +₁ ⟨ π₂ ∘ π₁ , π₂ ⟩) ∘ distributeˡ⁻¹ ≈˘⟨ (+₁-cong₂ (⟨⟩-cong₂ refl identityˡ) (⟨⟩-cong₂ refl identityˡ)) ⟩∘⟨refl ⟩
((π₂ ⁂ id) +₁ (π₂ ⁂ id)) ∘ distributeˡ⁻¹ ≈⟨ distributeˡ⁻¹-natural π₂ id id ⟩
distributeˡ⁻¹ ∘ (π₂ ⁂ (id +₁ id)) ≈⟨ refl⟩∘⟨ (⟨⟩-cong₂ refl (elimˡ ([]-unique id-comm-sym id-comm-sym))) ⟩
distributeˡ⁻¹ ∘ ⟨ π₂ ∘ π₁ , π₂ ⟩ ∎
strongMonad : StrongMonad monoidal
strongMonad = record { M = monad ; strength = strength }
module strength = Strength strength