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.

  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
  a ← ma ∷ M A
  b ← mb ∷ M B
  pure (a , b)

ma >>= Ξ» a β†’
  mb >>= Ξ» b β†’
    pure (a , b)

join (fmap (Ξ» a β†’
  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.

Monoidal functors from strong monadsπŸ”—

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-∘ _ _ $β‚š _)

  1. Applicative functors, or idioms, are usually defined as lax monoidal functors equipped with a compatible strength (not to be confused with strong monoidal functors).β†©οΈŽ