Zulip Chat Archive

Stream: mathlib4

Topic: Strong monads


Jad Ghalayini (Feb 13 2025 at 17:19):

Does it make sense to add a PR for a StrongMonad C class, which extends Monad C with data ensuring the monad is strong w.r.t. a MonoidalCategory C?

Jad Ghalayini (Feb 13 2025 at 17:20):

We'd also want an instance or somesuch stating that type-monads are always strong

Jad Ghalayini (Feb 13 2025 at 18:47):

Alright here's what I've got so far:

import Mathlib.CategoryTheory.Monad.Basic
import Mathlib.CategoryTheory.Monoidal.Category
import Mathlib.CategoryTheory.Monoidal.Types.Basic

namespace CategoryTheory

variable {C : Type u} [Category C] [MonoidalCategoryStruct C]

open MonoidalCategory

class LeftStrength (T : Monad C) where
  leftStrength : ∀(X Y : C), X ⊗ (T.obj Y) ⟶ T.obj (X ⊗ Y)
  leftStrength_naturality : ∀(X Y X' Y' : C) (f : X ⟶ X') (g : Y ⟶ Y'),
    (f ⊗ (T.map g)) ≫ leftStrength X' Y' = leftStrength X Y ≫ T.map (f ⊗ g)
  leftUnitor_leftStrength : ∀(X : C),
    (λ_ (T.obj X)).inv ≫ leftStrength (𝟙_ C) X = T.map (λ_ X).inv
  leftStrength_associator : ∀(X Y Z : C),
    leftStrength (X ⊗ Y) Z ≫ T.map (α_ X Y Z).hom
      = (α_ X Y (T.obj Z)).hom ≫ X ◁ leftStrength Y Z ≫ leftStrength X (Y ⊗ Z)
  η_leftStrength : ∀(X Y : C), X ◁ T.η.app Y ≫ leftStrength X Y = T.η.app (X ⊗ Y)
  μ_leftStrength : ∀(X Y : C),
    X ◁ T.μ.app Y ≫ leftStrength X Y
      = leftStrength X (T.obj Y) ≫ T.map (leftStrength X Y) ≫ T.μ.app (X ⊗ Y)

attribute [reassoc] LeftStrength.leftStrength_naturality
attribute [reassoc] LeftStrength.leftUnitor_leftStrength
attribute [reassoc] LeftStrength.leftStrength_associator
attribute [reassoc] LeftStrength.η_leftStrength
attribute [reassoc] LeftStrength.μ_leftStrength

class RightStrength (T : Monad C) where
  rightStrength : ∀(X Y : C), T.obj X ⊗ Y ⟶ T.obj (X ⊗ Y)
  rightStrength_naturality : ∀(X Y X' Y' : C) (f : X ⟶ X') (g : Y ⟶ Y'),
    ((T.map f) ⊗ g) ≫ rightStrength X' Y' = rightStrength X Y ≫ T.map (f ⊗ g)
  rightUnitor_rightStrength : ∀(X : C),
    (ρ_ (T.obj X)).inv ≫ rightStrength X (𝟙_ C) = T.map (ρ_ X).inv
  rightStrength_associator : ∀(X Y Z : C),
    rightStrength X (Y ⊗ Z) ≫ T.map (α_ X Y Z).inv
      = (α_ (T.obj X) Y Z).inv ≫ rightStrength X Y ▷ Z ≫ rightStrength (X ⊗ Y) Z
  η_rightStrength : ∀(X Y : C), T.η.app X ▷ Y ≫ rightStrength X Y = T.η.app (X ⊗ Y)
  μ_rightStrength : ∀(X Y : C),
    T.μ.app X ▷ Y ≫ rightStrength X Y
      = rightStrength (T.obj X) Y ≫ T.map (rightStrength X Y) ≫ T.μ.app (X ⊗ Y)

attribute [reassoc] RightStrength.rightStrength_naturality
attribute [reassoc] RightStrength.rightUnitor_rightStrength
attribute [reassoc] RightStrength.rightStrength_associator
attribute [reassoc] RightStrength.η_rightStrength
attribute [reassoc] RightStrength.μ_rightStrength

class Strength (T : Monad C) extends LeftStrength T, RightStrength T where
  leftStrength_rightStrength : ∀(X Y Z : C),
    leftStrength X Y ▷ Z ≫ rightStrength (X ⊗ Y) Z
      = (α_ X (T.obj Y) Z).hom
      ≫ X ◁ rightStrength Y Z
      ≫ leftStrength X (Y ⊗ Z)
      ≫ T.map (α_ X Y Z).inv

attribute [reassoc] Strength.leftStrength_rightStrength

open LeftStrength RightStrength

@[reassoc]
theorem Strength.rightStrength_leftStrength {T : Monad C} [Strength T] (X Y Z : C) :
  X ◁ rightStrength Y Z ≫ leftStrength X (Y ⊗ Z)
    = (α_ X (T.obj Y) Z).inv ≫ leftStrength X Y ▷ Z ≫ rightStrength _ Z ≫ T.map (α_ X Y Z).hom
  := by simp [leftStrength_rightStrength_assoc]

instance Strength.ofType.{v} {T : Monad (Type v)} : Strength T := /- snip -/

class CommutativeMonad (T : Monad C) extends Strength T where
  is_commutative : ∀(X Y : C),
    leftStrength (T.obj X) Y ≫ T.map (rightStrength X Y) ≫ T.μ.app (X ⊗ Y)
      = rightStrength X (T.obj Y) ≫ T.map (leftStrength X Y) ≫ T.μ.app (X ⊗ Y)

end CategoryTheory

How does this look for a start?

Jad Ghalayini (Feb 13 2025 at 18:47):

Also, any idea where we might put the analogue of CommutativeMonad for regular type-valued monads?

Jad Ghalayini (Feb 13 2025 at 19:23):

Here's what that would look like btw:

import Mathlib.Tactic.Convert

class SeqComm (f : Type u → Type v) [Applicative f] : Prop where
  seq_comm {α β : Type u} (l : f α) (r : f β) :
    Prod.mk <$> l <*> r = (λr (l : α) => (l, r)) <$> r <*> l

theorem SeqComm.bind_pair_comm {m : Type u → Type v} [Monad m] [LawfulMonad m] [SeqComm m]
  {α β : Type u} (l : m α) (r : m β) :
  (do let l <- l; let r <- r; return (l, r)) = (do let r <- r; let l <- l; return (l, r)) := by
  convert SeqComm.seq_comm l r using 1 <;>
  simp [seq_eq_bind_map]

theorem SeqComm.bind_comm {m : Type u → Type v} [Monad m] [LawfulMonad m] [SeqComm m]
  {α β : Type u} (l : m α) (r : m β) (f : α → β → m γ) :
  (do let l <- l; let r <- r; f l r) = (do let r <- r; let l <- l; f l r) := calc
  _ = (do let l <- l; let r <- r; pure (l, r)) >>= (λ(l, r) => f l r) := by simp
  _ = _ := by rw [bind_pair_comm]; simp

Then any monad satisfying SeqComm (e.g. Option) would satisfy CommutativeMonad as well

Bhavik Mehta (Feb 13 2025 at 19:41):

I'd say strong monads are worth having from a mathematical point of view. I don't know if CommutativeMonad for type-valued monads are worth having: my inclination is that those would be valuable only if they're useful from a programming point of view.

Jad Ghalayini (Feb 13 2025 at 19:44):

Bhavik Mehta said:

I'd say strong monads are worth having from a mathematical point of view. I don't know if CommutativeMonad for type-valued monads are worth having: my inclination is that those would be valuable only if they're useful from a programming point of view.

Commutative monads should be useful for reasoning about programs since they allow re-ordering statements which do not share variables; a few good examples of such monads are Option, ReaderT, and WriterT when the underlying monoid is commutative.

For math, commutative monads give a lot of useful theorems; my goal is to show that strong monads induce a premonoidal category (PR https://github.com/leanprover-community/mathlib4/pull/21488) while commutative monads induce a monoidal category. Going further, a lot of linear algebra can be very elegantly derived from the fact that the free vector space monad is commutative; would be fun to see how this looks in general

Bhavik Mehta (Feb 13 2025 at 19:51):

I completely agree there are a lot of interesting theorems that could be proved for commutative monads!

Jad Ghalayini (Feb 13 2025 at 19:51):

Think it's worth it to put in a PR with what I've got now?

Jad Ghalayini (Feb 13 2025 at 19:52):

So just the strong monad stuff, and some little lemmas?

Bhavik Mehta (Feb 13 2025 at 19:54):

I'd say the strong monad stuff is worth a PR, yeah.

Kim Morrison (Feb 14 2025 at 08:42):

I'm a bit confused why everything is a class above.

Jad Ghalayini (Feb 14 2025 at 13:54):

@Kim Morrison tbf the main application I was thinking of was automatically instantiating things for monads over Set, and other similar cases

Jad Ghalayini (Feb 14 2025 at 13:54):

Eventually what I would like are theorems relating strong monads to monoidal/premonoidal categories


Last updated: Feb 28 2026 at 14:05 UTC