module Cat.Monoidal.Strength.Monad where
Strong monadsπ
Recall that a (left) strength for an endofunctor on a monoidal category consists of a natural transformation allowing us to βslideβ things from the ambient context into the functor. If is equipped with the structure of a monad, then it is natural to refine this notion to be compatible with the monad, yielding the notion of a (left/right-) strong monad.
module _ {o β} {C : Precategory o β} (Cα΅ : Monoidal-category C) (monad : Monad C) where open Cat.Reasoning C open Monoidal-category Cα΅ open Monad monad
record Left-monad-strength : Type (o β β) where field functor-strength : Left-strength Cα΅ M open Left-strength functor-strength public field left-strength-Ξ· : β {A B} β Ο β (id ββ Ξ· B) β‘ Ξ· (A β B) left-strength-ΞΌ : β {A B} β Ο β (id ββ ΞΌ B) β‘ ΞΌ (A β B) β Mβ Ο β Ο record Right-monad-strength : Type (o β β) where field functor-strength : Right-strength Cα΅ M open Right-strength functor-strength public field right-strength-Ξ· : β {A B} β Ο β (Ξ· A ββ id) β‘ Ξ· (A β B) right-strength-ΞΌ : β {A B} β Ο β (ΞΌ A ββ id) β‘ ΞΌ (A β B) β Mβ Ο β Ο record Monad-strength : Type (o β β) where field strength-left : Left-monad-strength strength-right : Right-monad-strength open Left-monad-strength strength-left hiding (functor-strength) public open Right-monad-strength strength-right hiding (functor-strength) public field strength-Ξ±β : β {A B C} β Mβ (Ξ±β A B C) β Ο β (Ο ββ id) β‘ Ο β (id ββ Ο) β Ξ±β A (Mβ B) C
Strong monads are of particular importance in the semantics of
effectful programming languages: while monads are used to model effects,
they do not capture the fact that monadic computations can make use of
information from the context; for example, consider the
following pseudo-Haskell program (in do
notation, then in
two possible desugared forms):
do
M A
a β ma β· M B
b β mb β· pure (a , b)
>>= Ξ» a β
ma >>= Ξ» b β
mb pure (a , b)
fmap (Ξ» a β
join (fmap (Ξ» b β
(a , b)) mb) ma)
Notice that mb
, and then a
, are available
under
abstractions:
this is no problem in a functional programming language like Haskell,
because monads are automatically enriched in the sense that the
functorial action fmap
is an internal morphism; in
other words, -monads
are strong. But the mathematical denotation of the above program in
a general monoidal category makes crucial use of the strengths, as we
will see below.
With this perspective in mind, the additional coherences imposed on a monad strength are quite natural: using the strength to slide into a βpureβ computation (that is, one in the image of the unit) should yield a pure computation, and using the strength twice before multiplying should be the same as using it once after multiplying: they express a sort of βinternal naturalityβ condition for the unit and multiplication with respect to the enrichment induced by the strength.
functor-strength : Strength Cα΅ M functor-strength .Strength.strength-left = strength-left .Left-monad-strength.functor-strength functor-strength .Strength.strength-right = strength-right .Right-monad-strength.functor-strength functor-strength .Strength.strength-Ξ±β = strength-Ξ±β private unquoteDecl left-eqv = declare-record-iso left-eqv (quote Left-monad-strength) Left-monad-strength-path : β {a b} β a .Left-monad-strength.functor-strength β‘ b .Left-monad-strength.functor-strength β a β‘ b Left-monad-strength-path p = Iso.injective left-eqv (Ξ£-prop-path (Ξ» _ β hlevel 1) p) private unquoteDecl right-eqv = declare-record-iso right-eqv (quote Right-monad-strength) Right-monad-strength-path : β {a b} β a .Right-monad-strength.functor-strength β‘ b .Right-monad-strength.functor-strength β a β‘ b Right-monad-strength-path p = Iso.injective right-eqv (Ξ£-prop-path (Ξ» _ β hlevel 1) p) private unquoteDecl strength-eqv = declare-record-iso strength-eqv (quote Monad-strength) Monad-strength-path : β {a b} β a .Monad-strength.strength-left β‘ b .Monad-strength.strength-left β a .Monad-strength.strength-right β‘ b .Monad-strength.strength-right β a β‘ b Monad-strength-path p q = Iso.injective strength-eqv (Ξ£-pathp p (Ξ£-prop-pathp (Ξ» _ _ β hlevel 1) q))
Monoidal functors from strong monadsπ
module _ {o β} {C : Precategory o β} {Cα΅ : Monoidal-category C} {monad : Monad C} where open Cat.Reasoning C open Monoidal-category Cα΅ open Monad monad private module M = Cat.Functor.Reasoning M open is-iso module _ (s : Monad-strength Cα΅ monad) where open Monad-strength s open Lax-monoidal-functor-on
The above program wasnβt picked at random β it witnesses the common functional programming wisdom that βevery monad is an applicative functor1β, whose theoretical underpinning is that, given a strong monad we can equip with the structure of a lax monoidal functor.
In fact, we can do so in two different ways, corresponding to sequencing the effects from left to right or from right to left:
left-Ο right-Ο : -β- Fβ (M FΓ M) => M Fβ -β- left-Ο = (mult β -β-) βnt nat-assoc-to (M βΈ left-strength) βnt right-strength' where unquoteDecl right-strength' = cohere-into right-strength' (-β- Fβ (M FΓ M) => M Fβ -β- Fβ (Id FΓ M)) (right-strength β (Id FΓ M)) right-Ο = (mult β -β-) βnt nat-assoc-to (M βΈ right-strength) βnt left-strength' where unquoteDecl left-strength' = cohere-into left-strength' (-β- Fβ (M FΓ M) => M Fβ -β- Fβ (M FΓ Id)) (left-strength β (M FΓ Id))
If the two ways are the same (thus if the above diagram commutes), we say that the monad (or the strength) is commutative.
is-commutative-strength : Type (o β β) is-commutative-strength = right-Ο β‘ left-Ο
We now complete the definition of the left-to-right monoidal
structure, which requires a bit of work. For the unit, we pick
the unit of the monad.
strengthβmonoidal : Lax-monoidal-functor-on Cα΅ Cα΅ M
strengthβmonoidal .Ξ΅ = Ξ· Unit
strengthβmonoidal .F-mult = left-Ο
The associator coherence is witnessed by the following
monstrosity commutative diagram.
strengthβmonoidal .F-Ξ±β = Mβ (Ξ±β _ _ _) β (ΞΌ _ β Mβ Ο β Ο) β ((ΞΌ _ β Mβ Ο β Ο) ββ id) β‘β¨ pulll (extendl (sym (mult.is-natural _ _ _))) β©β‘ (ΞΌ _ β Mβ (Mβ (Ξ±β _ _ _)) β Mβ Ο β Ο) β ((ΞΌ _ β Mβ Ο β Ο) ββ id) β‘β¨ pullr (pullr (pullr refl)) β©β‘ ΞΌ _ β Mβ (Mβ (Ξ±β _ _ _)) β Mβ Ο β Ο β ((ΞΌ _ β Mβ Ο β Ο) ββ id) β‘β¨ reflβ©ββ¨ M.pulll left-strength-Ξ±β β©β‘ ΞΌ _ β Mβ (Ο β (id ββ Ο) β Ξ±β _ _ _) β Ο β ((ΞΌ _ β Mβ Ο β Ο) ββ id) β‘β¨ reflβ©ββ¨ reflβ©ββ¨ β.popl right-strength-ΞΌ β©β‘ ΞΌ _ β Mβ (Ο β (id ββ Ο) β Ξ±β _ _ _) β (ΞΌ _ β Mβ Ο β Ο) β ((Mβ Ο β Ο) ββ id) β‘β¨ reflβ©ββ¨ reflβ©ββ¨ pullr (pullr (β.popl (Ο.is-natural _ _ _))) β©β‘ ΞΌ _ β Mβ (Ο β (id ββ Ο) β Ξ±β _ _ _) β ΞΌ _ β Mβ Ο β (Mβ (Ο ββ id) β Ο) β (Ο ββ id) β‘β¨ reflβ©ββ¨ M.popr (M.popr (pulll (sym (mult.is-natural _ _ _)))) β©β‘ ΞΌ _ β Mβ Ο β Mβ (id ββ Ο) β (ΞΌ _ β Mβ (Mβ (Ξ±β _ _ _))) β Mβ Ο β (Mβ (Ο ββ id) β Ο) β (Ο ββ id) β‘β¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ pullr (reflβ©ββ¨ reflβ©ββ¨ pullr refl) β©β‘ ΞΌ _ β Mβ Ο β Mβ (id ββ Ο) β ΞΌ _ β Mβ (Mβ (Ξ±β _ _ _)) β Mβ Ο β Mβ (Ο ββ id) β Ο β (Ο ββ id) β‘β¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ M.pulll3 strength-Ξ±β β©β‘ ΞΌ _ β Mβ Ο β Mβ (id ββ Ο) β ΞΌ _ β Mβ (Ο β (id ββ Ο) β Ξ±β _ _ _) β Ο β (Ο ββ id) β‘β¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ M.popr (M.popr (sym right-strength-Ξ±β)) β©β‘ ΞΌ _ β Mβ Ο β Mβ (id ββ Ο) β ΞΌ _ β Mβ Ο β Mβ (id ββ Ο) β Ο β Ξ±β _ _ _ β‘Λβ¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ extendl (Ο.is-natural _ _ _) β©β‘Λ ΞΌ _ β Mβ Ο β Mβ (id ββ Ο) β ΞΌ _ β Mβ Ο β Ο β (Mβ id ββ Ο) β Ξ±β _ _ _ β‘Λβ¨ reflβ©ββ¨ reflβ©ββ¨ extendl (mult.is-natural _ _ _) β©β‘Λ ΞΌ _ β Mβ Ο β ΞΌ _ β Mβ (Mβ (id ββ Ο)) β Mβ Ο β Ο β (Mβ id ββ Ο) β Ξ±β _ _ _ β‘Λβ¨ reflβ©ββ¨ extendl (mult.is-natural _ _ _) β©β‘Λ ΞΌ _ β ΞΌ _ β Mβ (Mβ Ο) β Mβ (Mβ (id ββ Ο)) β Mβ Ο β Ο β (Mβ id ββ Ο) β Ξ±β _ _ _ β‘Λβ¨ extendl mult-assoc β©β‘Λ ΞΌ _ β Mβ (ΞΌ _) β Mβ (Mβ Ο) β Mβ (Mβ (id ββ Ο)) β Mβ Ο β Ο β (Mβ id ββ Ο) β Ξ±β _ _ _ β‘Λβ¨ reflβ©ββ¨ reflβ©ββ¨ reflβ©ββ¨ M.extendl (Ο.is-natural _ _ _) β©β‘Λ ΞΌ _ β Mβ (ΞΌ _) β Mβ (Mβ Ο) β Mβ Ο β Mβ (id ββ Mβ Ο) β Ο β (Mβ id ββ Ο) β Ξ±β _ _ _ β‘β¨ reflβ©ββ¨ M.pulll3 (sym left-strength-ΞΌ) β©β‘ ΞΌ _ β Mβ (Ο β (id ββ ΞΌ _)) β Mβ (id ββ Mβ Ο) β Ο β (Mβ id ββ Ο) β Ξ±β _ _ _ β‘Λβ¨ reflβ©ββ¨ reflβ©ββ¨ extendl (Ο.is-natural _ _ _) β©β‘Λ ΞΌ _ β Mβ (Ο β (id ββ ΞΌ _)) β Ο β (Mβ id ββ Mβ Ο) β (Mβ id ββ Ο) β Ξ±β _ _ _ β‘β¨ reflβ©ββ¨ M.popr (extendl (sym (Ο.is-natural _ _ _))) β©β‘ ΞΌ _ β Mβ Ο β Ο β (Mβ id ββ ΞΌ _) β (Mβ id ββ Mβ Ο) β (Mβ id ββ Ο) β Ξ±β _ _ _ β‘β¨ pushr (pushr (reflβ©ββ¨ β.pulll3 ((reflβ©ββ¨ M.annihilate (idl _)) β M.eliml refl ,β refl))) β©β‘ (ΞΌ _ β Mβ Ο β Ο) β (id ββ (ΞΌ _ β Mβ Ο β Ο)) β Ξ±β _ _ _ β
The unitor coherences are relatively easy to prove.
strengthβmonoidal .F-Ξ»β = Mβ Ξ»β β (ΞΌ _ β Mβ Ο β Ο) β (Ξ· _ ββ id) β‘β¨ reflβ©ββ¨ pullr (pullr right-strength-Ξ·) β©β‘ Mβ Ξ»β β ΞΌ _ β Mβ Ο β Ξ· _ β‘Λβ¨ reflβ©ββ¨ reflβ©ββ¨ unit.is-natural _ _ _ β©β‘Λ Mβ Ξ»β β ΞΌ _ β Ξ· _ β Ο β‘β¨ reflβ©ββ¨ cancell right-ident β©β‘ Mβ Ξ»β β Ο β‘β¨ left-strength-Ξ»β β©β‘ Ξ»β β strengthβmonoidal .F-Οβ = Mβ Οβ β (ΞΌ _ β Mβ Ο β Ο) β (β id β ββ Ξ· _) β‘Λβ¨ apΒ‘ M-id β©β‘Λ Mβ Οβ β (ΞΌ _ β Mβ Ο β Ο) β (Mβ id ββ Ξ· _) β‘β¨ reflβ©ββ¨ pullr (pullr (Ο.is-natural _ _ _)) β©β‘ Mβ Οβ β ΞΌ _ β Mβ Ο β Mβ (id ββ Ξ· _) β Ο β‘β¨ reflβ©ββ¨ reflβ©ββ¨ M.pulll left-strength-Ξ· β©β‘ Mβ Οβ β ΞΌ _ β Mβ (Ξ· _) β Ο β‘β¨ reflβ©ββ¨ cancell left-ident β©β‘ Mβ Οβ β Ο β‘β¨ right-strength-Οβ β©β‘ Οβ β
Symmetryπ
In a braided monoidal category, we unsurprisingly say that a monad strength is symmetric if the underlying functor strength is: a strength with this property is equivalent to the data of a left (or right) strength, with the other one obtained by the braiding.
module _ (Cα΅ : Braided-monoidal Cα΅) where is-symmetric-monad-strength : Monad-strength Cα΅ monad β Type (o β β) is-symmetric-monad-strength s = is-symmetric-strength Cα΅ M Cα΅ functor-strength where open Monad-strength s
Dualityπ
Just as with functor strengths, the definitions of left and right monad strengths are completely dual up to reversing the tensor product.
monad-strength^rev : Left-monad-strength (Cα΅ ^rev) monad β Right-monad-strength Cα΅ monad monad-strength^rev = IsoβEquiv is where is : Iso _ _ is .fst l = record { functor-strength = strength^rev Cα΅ M .fst functor-strength ; right-strength-Ξ· = left-strength-Ξ· ; right-strength-ΞΌ = left-strength-ΞΌ } where open Left-monad-strength l is .snd .inv r = record { functor-strength = Equiv.from (strength^rev Cα΅ M) functor-strength ; left-strength-Ξ· = right-strength-Ξ· ; left-strength-ΞΌ = right-strength-ΞΌ } where open Right-monad-strength r is .snd .rinv _ = Right-monad-strength-path Cα΅ monad (Equiv.Ξ΅ (strength^rev Cα΅ M) _) is .snd .linv _ = Left-monad-strength-path (Cα΅ ^rev) monad (Equiv.Ξ· (strength^rev Cα΅ M) _)
Sets-monads are strongπ
The fact that -endofunctors are strong straightforwardly extends to the fact that monads are strong, by naturality of the unit and multiplication.
Sets-monad-strength : Left-monad-strength Setsβ monad Sets-monad-strength .functor-strength = Sets-strength M Sets-monad-strength .left-strength-Ξ· = ext Ξ» a b β sym (unit.is-natural _ _ (a ,_) $β _) Sets-monad-strength .left-strength-ΞΌ = ext Ξ» a mmb β sym (mult.is-natural _ _ (a ,_) $β _) β ap (ΞΌ _) (M-β _ _ $β _)
Applicative functors, or idioms, are usually defined as lax monoidal functors equipped with a compatible strength (not to be confused with strong monoidal functors).β©οΈ