{- Strong monads on cartesian categories as extension systems, i.e., in terms of unit and bind, deriving the rest of the structure https://ncatlab.org/nlab/show/extension+system -} {-# OPTIONS --safe --lossy-unification #-} module Cubical.Categories.Monad.Strength.Cartesian.ExtensionSystem where open import Cubical.Foundations.Prelude open import Cubical.Categories.Category open import Cubical.Categories.Functor renaming (𝟙⟨_⟩ to funcId) open import Cubical.Categories.Limits.BinProduct.More open import Cubical.Categories.Limits.Terminal open import Cubical.Categories.Limits.Terminal.More open import Cubical.Categories.Limits.Cartesian.Base open import Cubical.Categories.Comonad.Instances.Environment open import Cubical.Categories.Monad.ExtensionSystem as Monad open import Cubical.Tactics.CategorySolver.Reflection private variable ℓ ℓ' : Level module _ {C : Category ℓ ℓ'} (bp : BinProducts C) where open Category open BinProductsNotation bp -- open EnvNotation bp private variable Γ Δ a b c : C .ob γ δ : C [ Δ , Γ ] f g : C [ a , b ] -- s t : With Γ [ a , b ] -- TODO: reformulate this stuff in terms of Displayed categories. -- -- This is what Jacobs calls the "simple fibration" -- -- Env [ γ ][ a , b ] is a map Δ × a → b -- -- With is a fibered category over C. With : C → Cat -- -- A Strong extension system is a section of this bundle of categories -- open ExtensionSystemFor -- record StrongExtensionSystem : Type (ℓ-max ℓ ℓ') where -- field -- T : C .ob → C .ob -- systems : ∀ Γ → Monad.ExtensionSystemFor (With Γ) T -- -- η ∘ (γ × id) ≡ η -- η-natural : (γ ^*) ⟪ systems Γ .η {a = a} ⟫ ≡ systems Δ .η -- -- bind f ∘ (γ × id) ≡ bind (f ∘ (γ × id)) -- bind-natural : -- (γ ^*) ⟪ systems Γ .bind s ⟫ ≡ systems Δ .bind ((γ ^*) ⟪ s ⟫) -- -- | TODO: resulting η, bind are natural in all arguments -- -- If C further has a terminal object we get an "underlying monad" -- -- on C because Envs 𝟙 ≅ Id -- module _ (term : Terminal C) (SE : StrongExtensionSystem) where -- open StrongExtensionSystem SE -- open TerminalNotation C term -- open CartesianCategoryNotation (C , term , bp) -- open isIso -- -- This follows abstractly from showing (𝟙 ×-) is equivalent to -- -- the identity monad -- -- we'll just be explicit here -- E1 = systems 𝟙 -- -- f ∘ π₂ -- toWith1 : C [ a , b ] → With 𝟙 [ a , b ] -- toWith1 = C ._⋆_ (unitor-l .fst) -- -- f ∘ (! , id) -- fromWith1 : With 𝟙 [ a , b ] → C [ a , b ] -- fromWith1 = C ._⋆_ (unitor-l .snd .inv) -- fromTo : fromWith1 (toWith1 f) ≡ f -- fromTo = -- sym (C .⋆Assoc _ _ _) ∙ -- cong₂ (comp' C) refl (unitor-l .snd .sec) ∙ C .⋆IdL _ -- toFrom : toWith1 (fromWith1 f) ≡ f -- toFrom = -- sym (C .⋆Assoc _ _ _) ∙ -- cong₂ (comp' C) refl (unitor-l .snd .ret) ∙ C .⋆IdL _ -- -- TODO: recover a monad on the original category -- -- General principle would be that you can transport a monad -- -- along an equivalence of categories... -- global-ESF : Monad.ExtensionSystemFor C T -- global-ESF .η = fromWith1 (E1 .η) -- global-ESF .bind s = fromWith1 (E1 .bind (toWith1 s)) -- global-ESF .bind-r = -- cong fromWith1 (cong (E1 .bind) toFrom) ∙ -- cong fromWith1 (E1 .bind-r) ∙ ×β₂ -- global-ESF .bind-l {f = f} = -- -- (f o π₂)^+ ∘ (!,id) ∘ η ∘ (!, id) -- -- (f o π₂)^+ ∘ (!,η) ∘ η ∘ (!, id) -- ((C .⋆Assoc _ _ _) ∙ cong₂ (seq' C) refl -- (sym (C .⋆Assoc _ _ _) ∙ -- cong₂ (seq' C) -- (,p-natural ∙ cong₂ _,p_ (𝟙η' {g = π₁}) (C .⋆IdR _)) refl ∙ -- E1 .bind-l {f = (toWith1 f)} )) -- ∙ sym (C .⋆Assoc _ _ _) ∙ cong₂ (comp' C) refl ×β₂ ∙ C .⋆IdL _ -- -- ((f ∘ π₂)^+ ∘ (! , id)) ∘ ((g ∘ π₂)^+ ∘ (! , id)) -- global-ESF .bind-comp {f = f}{g = g} = -- -- ((f ∘ π₂)^+ ∘ (! , id)) ∘ ((g ∘ π₂)^+ ∘ (! , id)) -- lem -- f ∘𝟙 g = f^+ -- -- ((f ∘ π₂)^+ ∘ (π₁ , (g ∘ π₂)^+)) ∘ (! , id) -- ∙ cong₂ (seq' C) refl (cong₂ (comp' C) refl -- (,p-natural ∙ cong₂ _,p_ (𝟙η' {g = π₁}) (C .⋆IdR _)) ∙ E1 .bind-comp) -- ∙ cong₂ (seq' C) refl (cong (E1 .bind) -- -- (E1 .bind (toWith1 f)) ∘ (π₁ , (g ∘ π₂)) -- -- ≡ (E1 .bind (toWith f) ∘ g ∘ π₂) -- ((cong₂ (comp' C) refl (cong₂ _,p_ 𝟙η' (sym (C .⋆IdR _)) ∙ -- sym ,p-natural) ∙ C .⋆Assoc _ _ _) ∙ C .⋆Assoc _ _ _)) -- -- (((f ∘ π₂)^+ ∘ (! , id) ∘ g) ∘ π₂)^+ ∘ (! , id) -- where -- lem : comp' C (fromWith1 (E1 .bind (toWith1 f))) -- (fromWith1 (E1 .bind (toWith1 g))) ≡ -- ((E1 .bind (toWith1 f)) ∘⟨ C ⟩ -- ((!t ,p C .id) ∘⟨ C ⟩ E1 .bind (toWith1 g))) ∘⟨ C ⟩ -- ((!t ,p C .id)) -- lem = solveCat! C -- StrongMonad→Monad : Monad.ExtensionSystem C -- StrongMonad→Monad = T , global-ESF -- -- TODO: once we establish that T is a functor, -- -- we can show the following is natural -- σ : C [ Γ × T a , T (Γ × a) ] -- σ {Γ = Γ} = systems Γ .bind (fromWith1 (E1 .η)) -- module StrongMonadNotation {C : Category ℓ ℓ'} -- (bp : BinProducts C) (SE : StrongExtensionSystem bp) where -- open Category -- open Notation C bp -- open EnvNotation bp -- open StrongExtensionSystem SE public -- private -- variable -- Γ Δ a b c : C .ob -- γ δ : C [ Δ , Γ ] -- f g : C [ a , b ] -- s t : With Γ [ a , b ] -- open Functor -- PKleisli : C .ob → Category _ _ -- PKleisli Γ = Monad.Kleisli (With Γ) (T , systems Γ) -- PG : (Γ : C .ob) → Functor (PKleisli Γ) (With Γ) -- PG Γ = Monad.G ((With Γ)) ((T , systems Γ)) -- bindP : PKleisli Γ [ a , b ] → With Γ [ T a , T b ] -- bindP {Γ = Γ} = PG Γ .F-hom -- retP : PKleisli Γ [ a , a ] -- retP {Γ} = PKleisli Γ .id -- bindP-comp : bindP f ∘⟨ With Γ ⟩ bindP g ≡ bindP (bindP f ∘⟨ With Γ ⟩ g) -- bindP-comp {Γ = Γ} = ExtensionSystemFor.bind-comp (systems Γ) -- bindP-l : bindP f ∘⟨ With Γ ⟩ retP ≡ f -- bindP-l {Γ = Γ} = ExtensionSystemFor.bind-l (systems Γ) -- bindP-r : bindP (retP {a = a}) ≡ With Γ .id -- bindP-r {Γ = Γ} = ExtensionSystemFor.bind-r (systems Γ) -- open Functor -- pull : (γ : C [ Δ , Γ ]) → Functor (PKleisli Γ) (PKleisli Δ) -- pull γ .F-ob = λ z → z -- pull γ .F-hom f = (γ ^*) ⟪ f ⟫ -- pull γ .F-id = η-natural -- pull {Δ = Δ} γ .F-seq f g = -- (γ ^*) .F-seq _ _ ∙ cong₂ (seq' (With Δ)) refl bind-natural