open import Categories.Category.Core
open import Categories.Category.Distributive
open import Categories.Category.Restriction
open import Categories.Object.Terminal
open import Relation.Binary.Bundles using (Poset)
open import Monad.Helper
open import Data.Product using (_,_)
open import Algebra.Elgot
open import Category.Construction.ElgotAlgebras
open import Categories.FreeObjects.Free
open import Categories.Object.NaturalNumbers
open import Categories.Object.NaturalNumbers.Parametrized
open import Categories.Category.Construction.F-Algebras
import Categories.Morphism as M
import Categories.Morphism.Reasoning as MR
import Categories.Morphism.Properties as MP
import Monad.Instance.K as MIK
module Monad.Instance.K.OrderEnriched {o ℓ e} {C : Category o ℓ e} (distributive : Distributive C) (MK : MIK.MonadK distributive) where
open import Category.Distributive.Helper distributive
open Bundles
open MIK distributive
open Terminal terminal using (!; !-unique; !-unique₂; ⊤)
open MonadK MK
open Category C
open Equiv
open HomReasoning
open M C
open MR C
open MP C
open kleisliK using (extend; extend-≈)
open monadK using (μ)
open import Monad.Instance.K.Strong distributive MK
open import Monad.Instance.K.Commutative distributive MK
open import Monad.Instance.K.EquationalLifting distributive MK
open import Monad.Instance.K.Restriction distributive MK
open strongK using (strengthen; strength-assoc)
open Restriction KRestriction renaming (_↓ to _↓'; ↓-denestʳ to ↓-denestʳ'; ↓-cong to ↓-cong'; pidʳ to pidʳ'; ↓-comm to ↓-comm'; ↓-skew-comm to ↓-skew-comm')
open import Categories.Category.Restriction.Properties.Poset KRestriction
open import Categories.Category.Restriction.Properties KRestriction renaming (↓-idempotent to ↓-idempotent')
open import Categories.Object.NaturalNumbers.Parametrized.Properties.F-Algebras C cartesian coproducts
open import Categories.Monad.Commutative.Properties
open CommutativeProperties braided KCommutativeMonad
_↓ : ∀ {X Y} (f : X ⇒ K.₀ Y) → X ⇒ K.₀ X
f ↓ = K.₁ π₁ ∘ τ _ ∘ ⟨ id , f ⟩
↓-charac : ∀ {X Y} {f : X ⇒ K.₀ Y} → f ↓' ≈ f ↓
↓-charac {f = f} = begin
extend (η _ ∘ π₂) ∘ extend (ψ ∘ (η _ ∘ ! ⁂ η _)) ∘ extend (ψ ∘ (f ⁂ η _)) ∘ η _ ∘ ⟨ id , id ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ pullˡ kleisliK.identityʳ ⟩
extend (η _ ∘ π₂) ∘ extend (ψ ∘ (η _ ∘ ! ⁂ η _)) ∘ (ψ ∘ (f ⁂ η _)) ∘ ⟨ id , id ⟩ ≈⟨ refl⟩∘⟨ (extend-≈ (∘-resp-≈ʳ (sym (⁂∘⁂ ○ ⁂-cong₂ refl identityʳ))) ⟩∘⟨refl) ⟩
extend (η _ ∘ π₂) ∘ extend (ψ ∘ (η _ ⁂ η _) ∘ (! ⁂ id)) ∘ (ψ ∘ (f ⁂ η _)) ∘ ⟨ id , id ⟩ ≈⟨ refl⟩∘⟨ (extend-≈ (pullˡ ψ-η) ⟩∘⟨refl) ⟩
extend (η _ ∘ π₂) ∘ extend (η _ ∘ (! ⁂ id)) ∘ (ψ ∘ (f ⁂ η _)) ∘ ⟨ id , id ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ψ-τ' ⟩∘⟨refl ⟩
extend (η _ ∘ π₂) ∘ extend (η _ ∘ (! ⁂ id)) ∘ (σ _ ∘ (f ⁂ id)) ∘ ⟨ id , id ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ pullʳ ⁂∘Δ ⟩
extend (η _ ∘ π₂) ∘ extend (η _ ∘ (! ⁂ id)) ∘ σ _ ∘ ⟨ f , id ⟩ ≈⟨ pullˡ (kleisliK.sym-assoc ○ extend-≈ (pullˡ kleisliK.identityʳ)) ⟩
extend ((η _ ∘ π₂) ∘ (! ⁂ id)) ∘ σ _ ∘ ⟨ f , id ⟩ ≈⟨ (extend-≈ (pullʳ (project₂ ○ identityˡ))) ⟩∘⟨refl ⟩
extend (η _ ∘ π₂) ∘ σ _ ∘ ⟨ f , id ⟩ ≈˘⟨ sym (F₁⇒extend monadK π₂) ⟩∘⟨refl ⟩
K.₁ π₂ ∘ (K.₁ swap ∘ τ _ ∘ swap) ∘ ⟨ f , id ⟩ ≈⟨ refl⟩∘⟨ (pullʳ (pullʳ swap∘⟨⟩)) ⟩
K.₁ π₂ ∘ K.₁ swap ∘ τ _ ∘ ⟨ id , f ⟩ ≈⟨ pullˡ (sym K.homomorphism ○ K.F-resp-≈ project₂) ⟩
K.₁ π₁ ∘ τ _ ∘ ⟨ id , f ⟩ ∎
pidʳ : ∀ {X Y} {f : X ⇒ K.₀ Y} → extend f ∘ f ↓ ≈ f
pidʳ {f=f} = ∘-resp-≈ʳ (sym ↓-charac) ○ pidʳ'
↓-comm : ∀ {X Y Z} {f : X ⇒ K.₀ Y} {g : X ⇒ K.₀ Z} → extend (f ↓) ∘ g ↓ ≈ extend (g ↓) ∘ f ↓
↓-comm {f=f} {g} = ∘-resp-≈ (extend-≈ (sym ↓-charac)) (sym ↓-charac)
○ ↓-comm'
○ ∘-resp-≈ (extend-≈ ↓-charac) ↓-charac
↓-cong : ∀ {X Y} {f g : X ⇒ K.₀ Y} → f ≈ g → f ↓ ≈ g ↓
↓-cong f≈g = sym ↓-charac ○ ↓-cong' f≈g ○ ↓-charac
↓-denestʳ : ∀ {X Y Z} {f : X ⇒ K.₀ Y} {g : X ⇒ K.₀ Z} → (extend g ∘ f ↓) ↓ ≈ extend (g ↓) ∘ f ↓
↓-denestʳ {f = f} {g} = begin
(extend g ∘ f ↓) ↓ ≈˘⟨ ↓-charac ○ ↓-cong (∘-resp-≈ʳ ↓-charac) ⟩
(extend g ∘ f ↓') ↓' ≈⟨ ↓-denestʳ' ⟩
extend (g ↓') ∘ f ↓' ≈⟨ extend-≈ ↓-charac ⟩∘⟨ ↓-charac ⟩
extend (g ↓) ∘ f ↓ ∎
↓-idempotent : ∀ {X Y} {f : X ⇒ K.₀ Y} → f ↓ ↓ ≈ f ↓
↓-idempotent {f = f} = begin
f ↓ ↓ ≈˘⟨ ↓-charac ○ ↓-cong ↓-charac ⟩
f ↓' ↓' ≈⟨ ↓-idempotent' ⟩
f ↓' ≈⟨ ↓-charac ⟩
f ↓ ∎
_⇂_ : ∀ {X Y Z} (f : X ⇒ K.₀ Y) (g : X ⇒ K.₀ Z) → X ⇒ K.₀ Y
f ⇂ g = extend π₁ ∘ τ _ ∘ ⟨ f , g ⟩
⇂-cong₂ : ∀ {X Y Z} {f h : X ⇒ K.₀ Y} {g i : X ⇒ K.₀ Z} → f ≈ h → g ≈ i → f ⇂ g ≈ h ⇂ i
⇂-cong₂ eq₁ eq₂ = refl⟩∘⟨ refl⟩∘⟨ ⟨⟩-cong₂ eq₁ eq₂
restrict-η : ∀ {X Y} {f : X ⇒ K.₀ Y} → η X ⇂ f ≈ f ↓
restrict-η {X} {Y} {f} = begin
extend π₁ ∘ τ _ ∘ ⟨ η X , f ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityʳ identityˡ) ⟩
extend π₁ ∘ τ _ ∘ (η X ⁂ id) ∘ ⟨ id , f ⟩ ≈⟨ refl⟩∘⟨ pullˡ (τ-comm-id (η X)) ⟩
extend π₁ ∘ (K.₁ (η X ⁂ id) ∘ τ _) ∘ ⟨ id , f ⟩ ≈⟨ pullˡ (pullˡ (extend∘F₁ monadK π₁ (η X ⁂ id))) ⟩
(extend (π₁ ∘ (η X ⁂ id)) ∘ τ _) ∘ ⟨ id , f ⟩ ≈⟨ (kleisliK.extend-≈ project₁ ⟩∘⟨refl) ⟩∘⟨refl ⟩
(extend (η X ∘ π₁) ∘ τ _) ∘ ⟨ id , f ⟩ ≈⟨ pushˡ ((F₁⇒extend monadK π₁) ⟩∘⟨refl) ⟩
K.₁ π₁ ∘ τ _ ∘ ⟨ id , f ⟩ ∎
restrict-law : ∀ {X Y Z} (f : X ⇒ K.₀ Y) (g : X ⇒ K.₀ Z) → f ⇂ g ≈ extend f ∘ g ↓
restrict-law {X} {Y} {Z} f g = begin
extend π₁ ∘ τ (K.₀ Y , Z) ∘ ⟨ f , g ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityʳ identityˡ) ⟩
extend π₁ ∘ τ (K.₀ Y , Z) ∘ (f ⁂ id) ∘ ⟨ id , g ⟩ ≈⟨ refl⟩∘⟨ (pullˡ (τ-comm-id f)) ⟩
extend π₁ ∘ (K.₁ (f ⁂ id) ∘ τ (X , Z)) ∘ ⟨ id , g ⟩ ≈⟨ (refl⟩∘⟨ assoc) ○ pullˡ (pullʳ (sym K.homomorphism)) ⟩
(μ.η _ ∘ K.₁ (π₁ ∘ (f ⁂ id))) ∘ τ (X , Z) ∘ ⟨ id , g ⟩ ≈⟨ (refl⟩∘⟨ ((K.F-resp-≈ π₁∘⁂) ○ K.homomorphism)) ⟩∘⟨refl ⟩
(μ.η Y ∘ (K.₁ f ∘ K.₁ π₁)) ∘ τ (X , Z) ∘ ⟨ id , g ⟩ ≈⟨ sym-assoc ⟩∘⟨refl ○ assoc ⟩
extend f ∘ K.₁ π₁ ∘ τ _ ∘ ⟨ id , g ⟩ ∎
⇂∘ : ∀ {A X Y Z} {f : X ⇒ K.₀ Y} {g : X ⇒ K.₀ Z} {h : A ⇒ X} → (f ⇂ g) ∘ h ≈ (f ∘ h) ⇂ (g ∘ h)
⇂∘ {A} {X} {Y} {Z} {f} {g} {h} = pullʳ (pullʳ ⟨⟩∘)
η↓ : ∀ {X Y} (f : X ⇒ K.₀ Y) → (η (K.₀ Y) ∘ f) ↓ ≈ η X
η↓ {X} {Y} f = begin
K.₁ π₁ ∘ τ _ ∘ ⟨ id , η _ ∘ f ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identity² refl) ⟩
K.₁ π₁ ∘ τ _ ∘ (id ⁂ η _) ∘ ⟨ id , f ⟩ ≈⟨ refl⟩∘⟨ (pullˡ (τ-η _)) ⟩
K.₁ π₁ ∘ η _ ∘ ⟨ id , f ⟩ ≈⟨ pullˡ (K₁η π₁) ⟩
(η _ ∘ π₁) ∘ ⟨ id , f ⟩ ≈⟨ cancelʳ project₁ ⟩
η _ ∎
⇂-assoc : ∀ {A X Y Z} {f : X ⇒ K.₀ Y} {g : X ⇒ K.₀ Z} {h : X ⇒ K.₀ A} → (f ⇂ g) ⇂ h ≈ f ⇂ (g ⇂ h)
⇂-assoc {A} {X} {Y} {Z} {f} {g} {h} = begin
(f ⇂ g) ⇂ h ≈⟨ restrict-law _ _ ○ ∘-resp-≈ˡ (extend-≈ (restrict-law _ _)) ⟩
extend (extend f ∘ g ↓) ∘ h ↓ ≈˘⟨ pullˡ (sym kleisliK.assoc) ⟩
extend f ∘ extend (g ↓) ∘ h ↓ ≈˘⟨ refl⟩∘⟨ ↓-denestʳ ⟩
extend f ∘ ((extend g ∘ h ↓) ↓) ≈˘⟨ restrict-law _ _ ○ ∘-resp-≈ʳ (↓-cong (restrict-law _ _)) ⟩
f ⇂ (g ⇂ h) ∎
infixr 10 _⊑_
_⊑_ : ∀ {X Y} (f g : X ⇒ K.₀ Y) → Set e
f ⊑ g = f ≈ g ⇂ f
module PartialOrder where
private
_≤_ : ∀ {X Y} (f g : X ⇒ K.₀ Y) → Set e
_≤_ {X} {Y} = _≤'_
where open Poset (poset X Y) using () renaming (_≤_ to _≤'_)
≤⇔⊑-helper' : ∀ {X Y} {f g : X ⇒ K.₀ Y} → extend g ∘ f ↓ ≈ extend π₁ ∘ τ _ ∘ ⟨ g , f ⟩
≤⇔⊑-helper' {X} {Y} {f} {g} = begin
extend g ∘ K.₁ π₁ ∘ τ _ ∘ ⟨ id , f ⟩ ≈⟨ pullˡ (extend∘F₁ monadK g π₁) ⟩
extend (g ∘ π₁) ∘ τ _ ∘ ⟨ id , f ⟩ ≈˘⟨ (extend-≈ project₁) ⟩∘⟨refl ⟩
extend (π₁ ∘ (g ⁂ id)) ∘ τ _ ∘ ⟨ id , f ⟩ ≈˘⟨ pullˡ ((extend∘F₁ monadK π₁ (g ⁂ id))) ⟩
extend π₁ ∘ K.₁ (g ⁂ id) ∘ τ _ ∘ ⟨ id , f ⟩ ≈˘⟨ refl⟩∘⟨ (extendʳ (strongK.strengthen.commute (g , id))) ⟩
extend π₁ ∘ τ _ ∘ (g ⁂ K.₁ id) ∘ ⟨ id , f ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityʳ (elimˡ K.identity)) ⟩
extend π₁ ∘ τ _ ∘ ⟨ g , f ⟩ ∎
≤⇔⊑-helper : ∀ {X Y} {f g : X ⇒ K.₀ Y} → extend g ∘ f ↓' ≈ extend π₁ ∘ τ _ ∘ ⟨ g , f ⟩
≤⇔⊑-helper {X} {Y} {f} {g} = ∘-resp-≈ʳ ↓-charac ○ ≤⇔⊑-helper'
≤⇒⊑ : ∀ {X Y} {f g : X ⇒ K.₀ Y} → f ≤ g → f ⊑ g
≤⇒⊑ {X} {Y} {f} {g} leq = begin
f ≈⟨ leq ⟩
extend g ∘ f ↓' ≈⟨ ≤⇔⊑-helper ⟩
extend π₁ ∘ τ _ ∘ ⟨ g , f ⟩ ∎
⊑⇒≤ : ∀ {X Y} {f g : X ⇒ K.₀ Y} → f ⊑ g → f ≤ g
⊑⇒≤ {X} {Y} {f} {g} sqleq = begin
f ≈⟨ sqleq ⟩
extend π₁ ∘ τ _ ∘ ⟨ g , f ⟩ ≈˘⟨ ≤⇔⊑-helper ⟩
extend g ∘ f ↓' ∎
⊑-refl : ∀ {X Y} {f : X ⇒ K.₀ Y} → f ⊑ f
⊑-refl {X} {Y} = ≤⇒⊑ (refl' refl)
where open Poset (poset X Y) using () renaming (reflexive to refl')
⊑-trans : ∀ {X Y} {f g h : X ⇒ K.₀ Y} → f ⊑ g → g ⊑ h → f ⊑ h
⊑-trans {X} {Y} f⊑g g⊑h = ≤⇒⊑ (trans' (⊑⇒≤ f⊑g) (⊑⇒≤ g⊑h))
where open Poset (poset X Y) using () renaming (trans to trans')
⊑-antisym : ∀ {X Y} {f g : X ⇒ K.₀ Y} → f ⊑ g → g ⊑ f → f ≈ g
⊑-antisym {X} {Y} f⊑g g⊑f = antisym' (⊑⇒≤ f⊑g) (⊑⇒≤ g⊑f)
where open Poset (poset X Y) using () renaming (antisym to antisym')
open PartialOrder public
⊑∘ʳ : ∀ {A X Y} {f g : X ⇒ K.₀ Y} {h : Y ⇒ K.₀ A} → f ⊑ g → (extend h ∘ f) ⊑ (extend h ∘ g)
⊑∘ʳ {A} {X} {Y} {f} {g} {h} leq = begin
extend h ∘ f ≈⟨ refl⟩∘⟨ leq ⟩
extend h ∘ (g ⇂ f) ≈⟨ refl⟩∘⟨ (restrict-law g f) ⟩
extend h ∘ extend g ∘ f ↓ ≈⟨ pullˡ kleisliK.sym-assoc ⟩
extend (extend h ∘ g) ∘ f ↓ ≈˘⟨ ∘-resp-≈ˡ (extend-≈ pidʳ) ⟩
extend (extend (extend h ∘ g) ∘ ((extend h ∘ g) ↓)) ∘ f ↓ ≈˘⟨ pullˡ kleisliK.sym-assoc ⟩
extend (extend h ∘ g) ∘ extend ((extend h ∘ g) ↓) ∘ f ↓ ≈˘⟨ refl⟩∘⟨ ↓-denestʳ ⟩
extend (extend h ∘ g) ∘ (extend (extend h ∘ g) ∘ (f ↓)) ↓ ≈˘⟨ pullˡ kleisliK.sym-assoc ⟩
extend h ∘ extend g ∘ (extend (extend h ∘ g) ∘ (f ↓)) ↓ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ↓-cong (∘-resp-≈ˡ kleisliK.assoc ○ assoc) ⟩
extend h ∘ extend g ∘ (extend h ∘ extend g ∘ f ↓)↓ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ ↓-cong (refl⟩∘⟨ leq ○ ∘-resp-≈ʳ (restrict-law g f) ) ⟩
extend h ∘ extend g ∘ (extend h ∘ f)↓ ≈⟨ pullˡ (kleisliK.sym-assoc) ⟩
extend (extend h ∘ g) ∘ (extend h ∘ f)↓ ≈˘⟨ restrict-law (extend h ∘ g) (extend h ∘ f) ⟩
(extend h ∘ g) ⇂ (extend h ∘ f) ∎
⊑∘ˡ : ∀ {A X Y} {f g : X ⇒ K.₀ Y} {h : A ⇒ X} → f ⊑ g → (f ∘ h) ⊑ (g ∘ h)
⊑∘ˡ {A} {X} {Y} {f} {g} {h} leq = begin
f ∘ h ≈⟨ leq ⟩∘⟨refl ⟩
(g ⇂ f) ∘ h ≈⟨ ⇂∘ ⟩
((g ∘ h) ⇂ (f ∘ h)) ∎
⊑-cong₂ : ∀ {X Y} {f g h i : X ⇒ K.₀ Y} → f ≈ h → g ≈ i → f ⊑ g → h ⊑ i
⊑-cong₂ eq₁ eq₂ leq = (sym eq₁) ○ leq ○ ⇂-cong₂ eq₂ eq₁
f↓⊑η : ∀ {X Y} {f : X ⇒ K.₀ Y} → f ↓ ⊑ η X
f↓⊑η {X} {Y} {f} = begin
f ↓ ≈˘⟨ ↓-idempotent ⟩
(f ↓)↓ ≈˘⟨ restrict-η ⟩
η X ⇂ (f ↓) ∎
bot : ∀ {X} {Y} → X ⇒ K.₀ Y
bot = i₂ #
bot∘! : ∀ {X} {Y} → bot {X} {Y} ≈ bot {⊤} {Y} ∘ !
bot∘! = #-Uniformity (algebras _) inject₂
bot-absorbs : ∀ {X Y Z} {f : Z ⇒ X} → bot {X} {Y} ∘ f ≈ bot {Z} {Y}
bot-absorbs {X} {Y} {Z} {f} = begin
bot {X} {Y} ∘ f ≈⟨ bot∘! ⟩∘⟨refl ⟩
(bot ∘ !) ∘ f ≈⟨ pullʳ (sym (!-unique (! ∘ f))) ⟩
bot ∘ ! ≈˘⟨ bot∘! ⟩
bot {Z} {Y} ∎
bot⊑f : ∀ {X} {Y} {f : X ⇒ K.₀ Y} → bot ⊑ f
bot⊑f {X} {Y} {f} = sym (begin
extend π₁ ∘ τ _ ∘ ⟨ f , i₂ # ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityˡ identityʳ) ⟩
extend π₁ ∘ τ _ ∘ (id ⁂ i₂ #) ∘ ⟨ f , id ⟩ ≈⟨ refl⟩∘⟨ (pullˡ (τ-comm i₂)) ⟩
extend π₁ ∘ ((τ _ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ i₂))# ∘ ⟨ f , id ⟩ ≈⟨ refl⟩∘⟨ ((#-resp-≈ (algebras (K.₀ Y × Y)) (refl⟩∘⟨ distributeˡ⁻¹-i₂)) ⟩∘⟨refl) ⟩
extend π₁ ∘ ((τ _ +₁ id) ∘ i₂)# ∘ ⟨ f , id ⟩ ≈⟨ refl⟩∘⟨ ((#-resp-≈ (algebras (K.₀ Y × Y)) ((inject₂ ○ identityʳ))) ⟩∘⟨refl) ⟩
extend π₁ ∘ i₂ # ∘ ⟨ f , id ⟩ ≈⟨ pullˡ (extend-preserve π₁ i₂) ⟩
((extend π₁ +₁ id) ∘ i₂) # ∘ ⟨ f , id ⟩ ≈⟨ (#-resp-≈ (algebras Y) (inject₂ ○ identityʳ)) ⟩∘⟨refl ⟩
i₂ # ∘ ⟨ f , id ⟩ ≈˘⟨ #-Uniformity (algebras Y) inject₂ ⟩
i₂ # ∎)
τ-strict : ∀ {X Y Z} → τ (X , Y) ∘ (id ⁂ bot {Z} {Y}) ≈ bot
τ-strict {X} {Y} {Z} = begin
τ _ ∘ (id ⁂ i₂ #) ≈⟨ τ-comm i₂ ⟩
((τ _ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ i₂)) # ≈⟨ #-resp-≈ (algebras _) (refl⟩∘⟨ distributeˡ⁻¹-i₂) ⟩
((τ _ +₁ id) ∘ i₂) # ≈⟨ #-resp-≈ (algebras _) (inject₂ ○ identityʳ) ⟩
(i₂ #) ∎
τ-monotonicity : ∀ {X Y} {f g : X ⇒ K.₀ Y} → f ⊑ g → (τ (X , Y) ∘ ⟨ id , f ⟩) ⊑ (τ (X , Y) ∘ ⟨ id , g ⟩)
τ-monotonicity {f = f} {g} f⊑g = begin
τ _ ∘ ⟨ id , f ⟩ ≈⟨ refl⟩∘⟨ (⟨⟩-cong₂ refl (f⊑g ○ restrict-law g f)) ⟩
τ _ ∘ ⟨ id , extend g ∘ f ↓ ⟩ ≈˘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identity² refl) ⟩
τ _ ∘ (id ⁂ extend g) ∘ ⟨ id , f ↓ ⟩ ≈⟨ pullˡ (sym (τ-extendʳ g)) ○ assoc ⟩
extend (τ _ ∘ (id ⁂ g)) ∘ τ _ ∘ ⟨ id , K.₁ π₁ ∘ τ _ ∘ ⟨ id , f ⟩ ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identity² refl) ⟩
extend (τ _ ∘ (id ⁂ g)) ∘ τ _ ∘ (id ⁂ K.₁ π₁) ∘ ⟨ id , τ _ ∘ ⟨ id , f ⟩ ⟩ ≈⟨ refl⟩∘⟨ (extendʳ (strengthen.commute (id , π₁))) ⟩
extend (τ _ ∘ (id ⁂ g)) ∘ K.₁ (id ⁂ π₁) ∘ τ _ ∘ ⟨ id , τ _ ∘ ⟨ id , f ⟩ ⟩ ≈⟨ pullˡ (extend∘F₁ monadK _ _ ○ extend-≈ (pullʳ (⁂∘⁂ ○ ⁂-cong₂ identity² refl))) ⟩
extend (τ _ ∘ (id ⁂ g ∘ π₁)) ∘ τ _ ∘ ⟨ id , τ _ ∘ ⟨ id , f ⟩ ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identity² refl) ⟩
extend (τ _ ∘ (id ⁂ g ∘ π₁)) ∘ τ _ ∘ (id ⁂ τ _) ∘ ⟨ id , ⟨ id , f ⟩ ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ refl⟩∘⟨ assocˡ∘⟨⟩ ⟩
extend (τ _ ∘ (id ⁂ g ∘ π₁)) ∘ τ _ ∘ (id ⁂ τ _) ∘ assocˡ ∘ ⟨ Δ , f ⟩ ≈⟨ refl⟩∘⟨ (sym-assoc ○ pullˡ (assoc ○ sym strength-assoc)) ⟩
extend (τ _ ∘ (id ⁂ g ∘ π₁)) ∘ (K.₁ assocˡ ∘ τ _) ∘ ⟨ Δ , f ⟩ ≈⟨ pullˡ (pullˡ (extend∘F₁ monadK _ _)) ⟩
(extend ((τ _ ∘ (id ⁂ g ∘ π₁)) ∘ assocˡ) ∘ τ _) ∘ ⟨ Δ , f ⟩ ≈⟨ (extend-≈ (pullʳ (⟨⟩∘ ○ ⟨⟩-cong₂ (pullʳ project₁ ○ identityˡ) (pullʳ project₂ ○ pullʳ project₁))) ⟩∘⟨refl) ⟩∘⟨refl ⟩
(extend (τ _ ∘ ⟨ π₁ ∘ π₁ , g ∘ π₂ ∘ π₁ ⟩) ∘ τ _) ∘ ⟨ Δ , f ⟩ ≈˘⟨ ((extend-≈ (∘-resp-≈ʳ (⟨⟩∘ ○ ⟨⟩-cong₂ (∘-resp-≈ˡ identityˡ) assoc))) ⟩∘⟨refl) ⟩∘⟨refl ⟩
(extend (τ _ ∘ (id ⁂ g) ∘ π₁) ∘ τ _) ∘ ⟨ Δ , f ⟩ ≈˘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityʳ identityˡ) ⟩
(extend (τ _ ∘ (id ⁂ g) ∘ π₁) ∘ τ _) ∘ (Δ ⁂ id) ∘ ⟨ id , f ⟩ ≈⟨ pullʳ (extendʳ (τ-comm-id Δ)) ⟩
extend (τ _ ∘ (id ⁂ g) ∘ π₁) ∘ K.₁ (Δ ⁂ id) ∘ τ _ ∘ ⟨ id , f ⟩ ≈⟨ pullˡ (extend∘F₁ monadK _ _ ○ extend-≈ (pullʳ (pullʳ project₁ ○ pullˡ ⁂∘Δ))) ⟩
extend (τ _ ∘ ⟨ id , g ⟩ ∘ π₁) ∘ τ _ ∘ ⟨ id , f ⟩ ≈˘⟨ pullˡ (extend∘F₁ monadK _ _ ○ extend-≈ assoc) ⟩
extend (τ _ ∘ ⟨ id , g ⟩) ∘ K.₁ π₁ ∘ τ _ ∘ ⟨ id , f ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ project₁ identityˡ) ⟩
extend (τ _ ∘ ⟨ id , g ⟩) ∘ K.₁ π₁ ∘ τ _ ∘ (π₁ ⁂ id) ∘ ⟨ Δ , f ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ extendʳ (τ-comm-id π₁) ⟩
extend (τ _ ∘ ⟨ id , g ⟩) ∘ K.₁ π₁ ∘ K.₁ (π₁ ⁂ id) ∘ τ _ ∘ ⟨ Δ , f ⟩ ≈⟨ refl⟩∘⟨ pullˡ (sym monadK.F.homomorphism ○ monadK.F.F-resp-≈ project₁) ⟩
extend (τ _ ∘ ⟨ id , g ⟩) ∘ K.₁ (π₁ ∘ π₁) ∘ τ _ ∘ ⟨ Δ , f ⟩ ≈˘⟨ refl⟩∘⟨ (pullˡ (pullˡ (sym monadK.F.homomorphism ○ monadK.F.F-resp-≈ project₁)) ○ assoc) ⟩
extend (τ _ ∘ ⟨ id , g ⟩) ∘ K.₁ π₁ ∘ (K.₁ assocˡ ∘ τ _) ∘ ⟨ Δ , f ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (sym-assoc ○ pullˡ (assoc ○ sym strength-assoc)) ⟩
extend (τ _ ∘ ⟨ id , g ⟩) ∘ K.₁ π₁ ∘ τ _ ∘ (id ⁂ τ _) ∘ assocˡ ∘ ⟨ Δ , f ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ refl⟩∘⟨ refl⟩∘⟨ assocˡ∘⟨⟩ ⟩
extend (τ _ ∘ ⟨ id , g ⟩) ∘ K.₁ π₁ ∘ τ _ ∘ (id ⁂ τ _) ∘ ⟨ id , ⟨ id , f ⟩ ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identity² refl) ⟩
extend (τ _ ∘ ⟨ id , g ⟩) ∘ K.₁ π₁ ∘ τ _ ∘ ⟨ id , τ _ ∘ ⟨ id , f ⟩ ⟩ ≈˘⟨ restrict-law _ _ ⟩
((τ _ ∘ ⟨ id , g ⟩) ⇂ (τ _ ∘ ⟨ id , f ⟩)) ∎
∘-right-strict : ∀ {X Y Z} (f : X ⇒ K.₀ Y) → extend f ∘ bot {Z} {X} ≈ bot
∘-right-strict f = begin
extend f ∘ bot ≈⟨ extend-preserve f i₂ ⟩
((extend f +₁ id) ∘ i₂) # ≈⟨ #-resp-≈ (algebras _) (inject₂ ○ identityʳ) ⟩
bot ∎
bot-restrict : ∀ {X Y Z} (f : X ⇒ K.₀ Y) → f ⇂ (bot {X} {Z}) ≈ bot
bot-restrict f = begin
extend π₁ ∘ τ _ ∘ ⟨ f , bot ⟩ ≈˘⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityˡ identityʳ) ⟩
extend π₁ ∘ τ _ ∘ (id ⁂ bot) ∘ ⟨ f , id ⟩ ≈⟨ refl⟩∘⟨ (pullˡ τ-strict) ⟩
extend π₁ ∘ bot ∘ ⟨ f , id ⟩ ≈⟨ pullˡ (∘-right-strict π₁) ⟩
bot ∘ ⟨ f , id ⟩ ≈˘⟨ #-Uniformity (algebras _) inject₂ ⟩
bot ∎
bot-preserves : ∀ {X Y Z} {f : X ⇒ K.₀ Y + X} → bot {K.₀ Y} {Z} ∘ f # ≈ ((bot +₁ id) ∘ f)#
bot-preserves {f = f} = begin
bot ∘ f # ≈⟨ bot-absorbs ⟩
bot ≈⟨ ⊑-antisym bot⊑f helper ⟩
extend bot ∘ ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f))# ∘ Δ
≈⟨ pullˡ (extend-preserve bot ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) ○ #-resp-≈ (algebras _) (pullˡ (+₁∘+₁ ○ +₁-cong₂ refl identity²))) ⟩
((extend bot ∘ η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f))# ∘ Δ ≈⟨ (#-resp-≈ (algebras _) (∘-resp-≈ˡ (+₁-cong₂ (pullˡ kleisliK.identityʳ ○ bot-absorbs) refl))) ⟩∘⟨refl ⟩
((bot +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f))# ∘ Δ ≈⟨ pushˡ (#-Uniformity (algebras _) (begin
(id +₁ π₂) ∘ (bot +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f) ≈⟨ extendʳ (+₁∘+₁ ○ +₁-cong₂ (identityˡ ○ sym bot-absorbs) id-comm ○ sym +₁∘+₁) ⟩
(bot +₁ id) ∘ (π₂ +₁ π₂) ∘ distributeˡ⁻¹ ∘ (id ⁂ f) ≈⟨ refl⟩∘⟨ (pullˡ distributeˡ⁻¹-π₂ ) ⟩
(bot +₁ id) ∘ π₂ ∘ (id ⁂ f) ≈⟨ ∘-resp-≈ʳ project₂ ○ sym-assoc ⟩
((bot +₁ id) ∘ f) ∘ π₂ ∎)) ⟩
((bot +₁ id) ∘ f)# ∘ π₂ ∘ Δ ≈⟨ elimʳ project₂ ⟩
((bot +₁ id) ∘ f)# ∎
where
ηπ₁-strict : ∀ {X Y Z} (f : Z ⇒ Y + Z) → ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f))# ⊑ (η X ∘ π₁)
ηπ₁-strict f = begin
((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) # ≈⟨ introʳ (⁂∘Δ ○ ⁂-η) ⟩
((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) # ∘ (π₁ ⁂ π₂) ∘ Δ ≈˘⟨ pushˡ (#-Uniformity (algebras _) by-uniformity) ⟩
((η _ ∘ π₁ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)))# ∘ Δ ≈˘⟨ (#-resp-≈ (algebras _) ((+₁-cong₂ (extendʳ (K₁η (π₁ ∘ π₁)) ○ ∘-resp-≈ʳ (pullʳ (project₁ ○ identityˡ))) refl) ⟩∘⟨refl)) ⟩∘⟨refl ⟩
((K.₁ (π₁ ∘ π₁) ∘ η _ ∘ (id ⁂ π₁) +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)))# ∘ Δ ≈˘⟨ (#-resp-≈ (algebras _) ((+₁-cong₂ (refl⟩∘⟨ (∘-resp-≈ʳ ( sym (⁂∘⁂ ○ ⁂-cong₂ identity² refl)) ○ pullˡ (τ-η (A×B , _)))) refl) ⟩∘⟨refl)) ⟩∘⟨refl ⟩
((K.₁ (π₁ ∘ π₁) ∘ τ _ ∘ (id ⁂ η _ ∘ π₁) +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)))# ∘ Δ ≈˘⟨ (#-resp-≈ (algebras _) (pullˡ (+₁∘+₁ ○ +₁-cong₂ assoc identity² ))) ⟩∘⟨refl ⟩
((K.₁ (π₁ ∘ π₁) ∘ τ _ +₁ id) ∘ ((id ⁂ η _ ∘ π₁) +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)))# ∘ Δ ≈˘⟨ (#-resp-≈ (algebras _) (refl⟩∘⟨ (extendʳ (sym (distributeˡ⁻¹-natural _ _ _) ○ ∘-resp-≈ˡ (+₁-cong₂ refl (⟨⟩-unique id-comm id-comm)))))) ⟩∘⟨refl ⟩
((K.₁ (π₁ ∘ π₁) ∘ τ _ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ (η _ ∘ π₁ +₁ id)) ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)))# ∘ Δ ≈⟨ (#-resp-≈ (algebras _) (refl⟩∘⟨ (refl⟩∘⟨ (⁂∘⁂ ○ ⁂-cong₂ identity² refl)))) ⟩∘⟨refl ⟩
((K.₁ (π₁ ∘ π₁) ∘ τ _ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ (η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)))# ∘ Δ ≈˘⟨ pullˡ (K-preserve _ _ ○ #-resp-≈ (algebras _) (pullˡ (+₁∘+₁ ○ +₁-cong₂ refl identity²))) ⟩
K.₁ (π₁ ∘ π₁) ∘ ((τ _ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ (η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)))# ∘ Δ ≈˘⟨ refl⟩∘⟨ (pullˡ (τ-comm _)) ⟩
K.₁ (π₁ ∘ π₁) ∘ τ _ ∘ (id ⁂ ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) #) ∘ Δ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ⁂∘Δ ⟩
K.₁ (π₁ ∘ π₁) ∘ τ _ ∘ ⟨ id , ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) # ⟩ ≈˘⟨ pullˡ (extend∘F₁ monadK π₁ _ ○ ∘-resp-≈ʳ (monadK.F.F-resp-≈ (project₁ ○ assoc)) ○ F₁⇒extend monadK (π₁ ∘ π₁)) ⟩
extend π₁ ∘ K.₁ (η _ ∘ π₁ ⁂ id) ∘ τ _ ∘ ⟨ id , ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) # ⟩ ≈˘⟨ refl⟩∘⟨ (extendʳ (τ-comm-id (η _ ∘ π₁))) ⟩
extend π₁ ∘ τ _ ∘ (η _ ∘ π₁ ⁂ id) ∘ ⟨ id , ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) # ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⟨⟩ ○ ⟨⟩-cong₂ identityʳ identityˡ) ⟩
extend π₁ ∘ τ _ ∘ ⟨ η _ ∘ π₁ , ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) # ⟩ ∎
where
by-uniformity : (id +₁ π₁ ⁂ π₂) ∘ (η _ ∘ π₁ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f))
≈ ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) ∘ (π₁ ⁂ π₂)
by-uniformity = begin
(id +₁ π₁ ⁂ π₂) ∘ (η _ ∘ π₁ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)) ≈⟨ pullˡ (+₁∘+₁ ○ +₁-cong₂ (identityˡ ○ ∘-resp-≈ʳ (sym project₁)) identityʳ) ⟩
(η _ ∘ π₁ ∘ (π₁ ⁂ π₂) +₁ π₁ ⁂ π₂) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)) ≈˘⟨ pullˡ (+₁∘+₁ ○ +₁-cong₂ assoc identityˡ) ⟩
(η _ ∘ π₁ +₁ id) ∘ (π₁ ⁂ π₂ +₁ π₁ ⁂ π₂) ∘ distributeˡ⁻¹ ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)) ≈⟨ refl⟩∘⟨ extendʳ (distributeˡ⁻¹-natural π₁ π₂ π₂) ⟩
(η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (π₁ ⁂ (π₂ +₁ π₂)) ∘ (id ⁂ distributeˡ⁻¹ ∘ (id ⁂ f)) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ (⁂∘⁂ ○ ⁂-cong₂ identityʳ refl) ⟩
(η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (π₁ ⁂ (π₂ +₁ π₂) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) ≈⟨ refl⟩∘⟨ refl⟩∘⟨ ⁂-cong₂ refl (pullˡ distributeˡ⁻¹-π₂ ○ project₂) ⟩
(η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (π₁ ⁂ f ∘ π₂) ≈˘⟨ pullʳ (pullʳ (⁂∘⁂ ○ ⁂-cong₂ identityˡ refl)) ⟩
((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) ∘ (π₁ ⁂ π₂) ∎
helper : (extend bot ∘ ((η _ ∘ π₁ +₁ id) ∘ distributeˡ⁻¹ ∘ (id ⁂ f)) # ∘ Δ) ⊑ bot
helper = ⊑-cong₂ refl (begin
extend bot ∘ (η _ ∘ π₁) ∘ Δ ≈⟨ pullˡ (pullˡ kleisliK.identityʳ) ○ cancelʳ project₁ ⟩
bot ∎) (⊑∘ʳ (⊑∘ˡ (ηπ₁-strict f)))
extend-strict : ∀ {X Y : Obj} → bot {K.₀ X} {Y} ≈ extend bot
extend-strict {X} {Y} = begin
bot ≈⟨ FreeObject.*-uniq (freealgebras X) bot (record { h = bot ; preserves = bot-preserves }) bot-absorbs ⟩
Elgot-Algebra-Morphism.h (((freealgebras X) FreeObject.*) bot) ≈⟨ sym (FreeObject.*-uniq (freealgebras X) {algebras Y} bot (record { h = extend bot ; preserves = extend-preserve bot _ }) kleisliK.identityʳ) ⟩
extend bot ∎
∘-left-strict : ∀ {X Y Z} (f : X ⇒ K.₀ Y) → extend (bot {Y} {Z}) ∘ f ≈ bot
∘-left-strict f = begin
extend bot ∘ f ≈˘⟨ extend-strict ⟩∘⟨refl ⟩
bot ∘ f ≈⟨ bot-absorbs ⟩
bot ∎
bot∘!-id : bot {⊤} {⊥} ∘ ! {K.₀ ⊥} ≈ id
bot∘!-id = begin
bot ∘ ! ≈⟨ bot-absorbs ⟩
bot ≈˘⟨ ∘-left-strict id ⟩
extend bot ∘ id ≈⟨ identityʳ ⟩
μ.η _ ∘ (K.₁ bot) ≈⟨ refl⟩∘⟨ K.F-resp-≈ (¡-unique₂ bot (η _)) ⟩
μ.η _ ∘ (K.₁ (η ⊥)) ≈⟨ monadK.identityˡ ⟩
id ∎
K⊥⊤ : K.₀ ⊥ ≅ ⊤
K⊥⊤ = record { from = ! ; to = bot ; iso = record { isoˡ = bot∘!-id ; isoʳ = !-unique₂ } }