Zulip Chat Archive
Stream: mathlib4
Topic: Premonoidal categories
Jad Ghalayini (Jan 22 2025 at 22:39):
Hello everyone!
I'm formalizing some programming language theory in Lean as a continuation of my paper: arXiv:2411.09347. In my work, I make extensive use of (symmetric) premonoidal categories, which generalize monoidal categories by removing the sliding condition.
Unfortunately, this means I can't use Mathlib's MonoidalCategory
class directly, so I had to implement a workaround: a somewhat unusual variant in discretion, with typical usage in refined-ssa. This implementation is really just a hack to work around Mathlib’s current design, so I’m not proposing it for merging. However, I’d like to discuss how we might improve Mathlib’s category hierarchy to better support premonoidal categories.
Currently, we have:
MonoidalCategoryStruct
: Defines tensor products and associators/unitors.MonoidalCategory
: Ensures thatMonoidalCategoryStruct
forms a valid monoidal category.
I propose adding two intermediate structures:
BinoidalCategory
: Ensures that left/right whiskering is functorial and definestensorHom
as their composition.PremonoidalCategory
: LikeMonoidalCategory
, but omittingtensorHom
composition and requiring associators/unitors to be central.
MonoidalCategory
would then remain as before, with the extra structure from PremonoidalCategory
handled via default members.
Some of the main things we can do with this are:
- Monoidal coherence extends to premonoidal categories, which I’ve already proved in
discretion
. BraidedCategory
can depend onPremonoidalCategory
instead ofMonoidalCategory
, and arguably should just depend onMonoidalCategoryStruct
.- The Kleisli category of a monoidal category is naturally premonoidal, giving a broad class of models for free.
If this is too much, we could drop BinoidalCategory
and introduce just PremonoidalCategory
, but I find BinoidalCategory
useful and aligned with the literature.
Would you be open to a pull request introducing these changes? It seems like a moderate refactor, so I’d likely need guidance from maintainers.
Thanks for your time, and apologies for the long post!
Jad
EDIT: removed distributive categories from the title as I left them out of this proposal since they complicate things
Johan Commelin (Jan 23 2025 at 05:09):
cc @Yuma Mizuno @Kim Morrison
Yuma Mizuno (Jan 23 2025 at 10:42):
@Jad Ghalayini I was not familiar with those concepts, but I think it's good to have a premonoidal category in mathlib.
While I cannot accurately estimate the required work, this may not be too much as many definitions and theorems about monoidal categories have already been written in terms of whiskering. You may find it helpful to see the formalization of bicategories (docs#CategoryTheory.Bicategory) where the horizontal composition (analogous to tensorHom) is not yet implemented.
Joël Riou (Jan 23 2025 at 13:26):
I am not completely sure I understand the exact axioms. Currently, the lemmas that are related to tensor_comp
are whiskerLeft_comp
, comp_whiskerRight
and whisker_exchange
. Is it whisker_exchange
which does not hold in your context?
In terms of design, my only concern is that when defining a new monoidal category structure, most users should not have to know about the intermediate classes. If MonoidalCategory
extends BinoidalCategory
, and BinoidalCategory
extends MonoidalCategoryStruct
, I think it would be ok, but I am not sure that MonoidalCategory
should extend PremonoidalCategory
.
(In #12728, with @Dagur Asgeirsson , we constructed the monoidal category structure on a localized category. In order to show the pentagon (and triangle) axioms, we need to use some lemmas most of which are consequences of the axioms from BinoidalCategory
. If this class was available, the proof would be slightly more direct .)
Jad Ghalayini (Jan 23 2025 at 14:36):
I already have an idea (hopefully) how to implement this, since I've implemented it along with coherence in discretion
. So I should just get along with the PR, then? I'm thinking of doing exactly what @Joël Riou said and making the hierarchy
MonoidalCategory
extends PremonoidalCategory
extends BinoidalCategory
extends MonoidalCategoryStruct
;
this is slightly ugly since a binoidal category in the literature does not require associator/unitor isomorphisms to exist, so future refactoring might be to shunt those higher in the hierarchy, but that's just perfectionism imo
Jad Ghalayini (Jan 23 2025 at 14:38):
Also, that's exactly right, it's whisker_exchange
which is invalid, which follows from tensor_comp
. The idea is to add whiskerLeft_comp
and whiskerRight_comp
as members and remove tensor_comp
, this follows from the definition of a premonoidal category where ⊗ is individually a functor in the left and right elements but is _not_ (necessarily) a bifunctor. Bifunctoriality is then recovered by adding tensor_comp
or whisker_exchange
, which in this setting are equivalent; doing the former is probably easier since it should minimize changes to existing MonoidalCategory
instances (since whiskerLeft_comp
and whiskerLeft_comp
can easily be derived from tensor_comp
)
Joël Riou (Jan 23 2025 at 14:59):
I think you may proceed with the PR. (I only have a doubt about whether MonoidalCategory
should extend PremonoidalCagegory
: if you find a way to make things so that no changes are required in downstream definitions, this would be fine though.)
Yuma Mizuno (Jan 23 2025 at 15:35):
@Jad Ghalayini If you are interested in generalizing the coherence tactic to PremonoidalCategory
setting but stack at some points, feel free to ask me. I found your codes for Central
instances around https://github.com/imbrem/discretion/blob/a90ccae04fe1bae94ab38005f71bc1a217526a18/Discretion/Premonoidal/Category.lean#L447 may be enough to implement the tactic, but you will need to write several lines of codes to handle these instances in meta setting.
Jad Ghalayini (Jan 23 2025 at 21:17):
Hello! I'm working on the PR and am mildly stuck: so I'm trying to get whiskerLeft_comp
and comp_whiskerRight
to be filled in by default for MonoidalCategory
instances as follows:
class MonoidalCategory (C : Type u) [𝒞 : Category.{v} C] extends PremonoidalCategory C where
/--
Composition of tensor products is tensor product of compositions:
`(f₁ ⊗ g₁) ∘ (f₂ ⊗ g₂) = (f₁ ∘ f₂) ⊗ (g₁ ⊗ g₂)`
-/
tensor_comp :
∀ {X₁ Y₁ Z₁ X₂ Y₂ Z₂ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (g₁ : Y₁ ⟶ Z₁) (g₂ : Y₂ ⟶ Z₂),
(f₁ ≫ g₁) ⊗ (f₂ ≫ g₂) = (f₁ ⊗ f₂) ≫ (g₁ ⊗ g₂) := by
aesop_cat
whiskerLeft_comp := whiskerLeft_comp_ofTensorHom tensorHom_def id_whiskerRight tensor_comp
comp_whiskerRight := comp_whiskerRight_ofTensorHom tensorHom_def whiskerLeft_id tensor_comp
Unfortunately... this doesn't work. It's a very minor change to fix all uses by just switching to an alternative constructor for MonoidalCategory
, but... there _must_ be a better way? How can we synthesize this nicely?
Yuma Mizuno (Jan 23 2025 at 21:23):
I'm a bit confused. PremonoidalCategory
doesn't have tensorHom
, right?
Jad Ghalayini (Jan 23 2025 at 21:23):
To make my life a (lot) easier I left it in
Jad Ghalayini (Jan 23 2025 at 21:24):
It makes sense for it to be defined as $f \otimes A ; B \otimes g$
Jad Ghalayini (Jan 23 2025 at 21:24):
And its useful because for central morphisms it behaves just like it does for monoidal categories
Jad Ghalayini (Jan 23 2025 at 21:24):
(indeed it is standard notation to write central morphisms with tensors and everything else with ltimes/rtimes)
Jad Ghalayini (Jan 23 2025 at 21:24):
Let me just show you what I've got:
Jad Ghalayini (Jan 23 2025 at 21:25):
class BinoidalCategory (C : Type u) [𝒞 : Category.{v} C] extends MonoidalCategoryStruct C where
-- NOTE: this is easily derivable from the others...
/-- Tensor product of identity maps is the identity: `(𝟙 X₁ ⊗ 𝟙 X₂) = 𝟙 (X₁ ⊗ X₂)` -/
tensor_id : ∀ X₁ X₂ : C, 𝟙 X₁ ⊗ 𝟙 X₂ = 𝟙 (X₁ ⊗ X₂) := by aesop_cat
tensorHom_def {X₁ Y₁ X₂ Y₂ : C} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂) :
f ⊗ g = (f ▷ X₂) ≫ (Y₁ ◁ g) := by
aesop_cat
/- Left whiskering of the identity is the identity: `X ◁ 𝟙 Y = 𝟙 (X ⊗ Y)` -/
whiskerLeft_id : ∀ (X Y : C), X ◁ 𝟙 Y = 𝟙 (X ⊗ Y) := by
aesop_cat
/- Right whiskering of the identity is the identity `𝟙 X ▷ Y = 𝟙 (X ⊗ Y)` -/
id_whiskerRight : ∀ (X Y : C), 𝟙 X ▷ Y = 𝟙 (X ⊗ Y) := by
aesop_cat
/- Left whiskering respects composition -/
whiskerLeft_comp (W : C) {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) :
W ◁ (f ≫ g) = W ◁ f ≫ W ◁ g := by
aesop_cat
/- Right whiskering respects composition -/
comp_whiskerRight {W X Y : C} (f : W ⟶ X) (g : X ⟶ Y) (Z : C) :
(f ≫ g) ▷ Z = f ▷ Z ≫ g ▷ Z := by
aesop_cat
class PremonoidalCategory (C : Type u) [𝒞 : Category.{v} C] extends BinoidalCategory C where
/-- Naturality of the associator isomorphism: `(f₁ ⊗ f₂) ⊗ f₃ ≃ f₁ ⊗ (f₂ ⊗ f₃)` -/
associator_naturality :
∀ {X₁ X₂ X₃ Y₁ Y₂ Y₃ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (f₃ : X₃ ⟶ Y₃),
((f₁ ⊗ f₂) ⊗ f₃) ≫ (α_ Y₁ Y₂ Y₃).hom = (α_ X₁ X₂ X₃).hom ≫ (f₁ ⊗ (f₂ ⊗ f₃)) := by
aesop_cat
/--
Naturality of the left unitor, commutativity of `𝟙_ C ⊗ X ⟶ 𝟙_ C ⊗ Y ⟶ Y` and `𝟙_ C ⊗ X ⟶ X ⟶ Y`
-/
leftUnitor_naturality :
∀ {X Y : C} (f : X ⟶ Y), 𝟙_ _ ◁ f ≫ (λ_ Y).hom = (λ_ X).hom ≫ f := by
aesop_cat
/--
Naturality of the right unitor: commutativity of `X ⊗ 𝟙_ C ⟶ Y ⊗ 𝟙_ C ⟶ Y` and `X ⊗ 𝟙_ C ⟶ X ⟶ Y`
-/
rightUnitor_naturality :
∀ {X Y : C} (f : X ⟶ Y), f ▷ 𝟙_ _ ≫ (ρ_ Y).hom = (ρ_ X).hom ≫ f := by
aesop_cat
/--
The pentagon identity relating the isomorphism between `X ⊗ (Y ⊗ (Z ⊗ W))` and `((X ⊗ Y) ⊗ Z) ⊗ W`
-/
pentagon :
∀ W X Y Z : C,
(α_ W X Y).hom ▷ Z ≫ (α_ W (X ⊗ Y) Z).hom ≫ W ◁ (α_ X Y Z).hom =
(α_ (W ⊗ X) Y Z).hom ≫ (α_ W X (Y ⊗ Z)).hom := by
aesop_cat
/--
The identity relating the isomorphisms between `X ⊗ (𝟙_ C ⊗ Y)`, `(X ⊗ 𝟙_ C) ⊗ Y` and `X ⊗ Y`
-/
triangle :
∀ X Y : C, (α_ X (𝟙_ _) Y).hom ≫ X ◁ (λ_ Y).hom = (ρ_ X).hom ▷ Y := by
aesop_cat
...
Jad Ghalayini (Jan 23 2025 at 21:25):
So we add whiskerLeft_comp and comp_whiskerRight
and remove tensor_comp
, which implies both of those
Jad Ghalayini (Jan 23 2025 at 21:26):
What we're basically saying is that - ⊗ A and A ⊗ - are functors, but - ⊗ - is not _necessarily_ a functor
Jad Ghalayini (Jan 23 2025 at 21:27):
Anyways the issue is it is not filling in the default fields whiskerLeft_comp
and comp_whiskerRight
so I need to add them in manually in about 5 places; it's not too big a change but it's moderately ugly
Jad Ghalayini (Jan 23 2025 at 21:27):
Simplest possible method is just to do that and then everything works
Jad Ghalayini (Jan 23 2025 at 21:27):
Making coherence
work shouldn't be _too_ hard after that
Jad Ghalayini (Jan 23 2025 at 21:28):
Since all you need to do is swap out everything Monoidal
for Premonoidal
Jad Ghalayini (Jan 23 2025 at 21:30):
I've also considered removing tensor_id
since its easily derivable from the other members of BinoidalCategory
Yuma Mizuno (Jan 23 2025 at 21:34):
I see. What I thought was not to include tensorHom
in the definition, as in the bicategory definition (docs#CategoryTheory.Bicategory). You can state tensor_comp
as the theorem instead of an axiom. This allows you to extract whisker_exchange
relation.
Yuma Mizuno (Jan 23 2025 at 21:35):
One question. Do the f_{1,2,3} in the naturality of associators have to be central?
Jad Ghalayini (Jan 23 2025 at 21:35):
I think this complicates things a lot; also it now means we need to do even more work fixing usages of MonoidalCategory, whereas now we just need to prove the whiskering lemmas
Jad Ghalayini (Jan 23 2025 at 21:36):
No, but I just realized that I forgot to make the associators themselves central, d'uh...
Jad Ghalayini (Jan 23 2025 at 21:36):
Which _also_ follows from tensor_comp, which makes _everything_ central
Jad Ghalayini (Jan 23 2025 at 21:36):
Now that's a bit more irritating
Jad Ghalayini (Jan 23 2025 at 21:37):
My current solution is to do something like LawfulMonad.mk', in which I have an alternative constructor for MonoidalCategory which acts exactly like the old constructor and fills in all the defaults
Jad Ghalayini (Jan 23 2025 at 21:37):
Jad Ghalayini said:
No, but I just realized that I forgot to make the associators themselves central, d'uh...
Note I did this in discretion
just forgot to port it over
Jad Ghalayini (Jan 23 2025 at 21:38):
What I wish is that there was a cleaner way to define default elements in child classes for parents
Yaël Dillies (Jan 23 2025 at 21:40):
Do you know you can redeclare parent fields when defining a child class? This gives you the opportunity to set a default value
Jad Ghalayini (Jan 23 2025 at 21:40):
I did redeclare those fields, and it's not working!
Jad Ghalayini (Jan 23 2025 at 21:41):
See, I wrote this:
class MonoidalCategory (C : Type u) [𝒞 : Category.{v} C] extends PremonoidalCategory C where
/--
Composition of tensor products is tensor product of compositions:
`(f₁ ⊗ g₁) ∘ (f₂ ⊗ g₂) = (f₁ ∘ f₂) ⊗ (g₁ ⊗ g₂)`
-/
tensor_comp :
∀ {X₁ Y₁ Z₁ X₂ Y₂ Z₂ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (g₁ : Y₁ ⟶ Z₁) (g₂ : Y₂ ⟶ Z₂),
(f₁ ≫ g₁) ⊗ (f₂ ≫ g₂) = (f₁ ⊗ f₂) ≫ (g₁ ⊗ g₂) := by
aesop_cat
whiskerLeft_comp := whiskerLeft_comp_ofTensorHom tensorHom_def id_whiskerRight tensor_comp
comp_whiskerRight := comp_whiskerRight_ofTensorHom tensorHom_def whiskerLeft_id tensor_comp
Jad Ghalayini (Jan 23 2025 at 21:41):
whiskerLeft_comp and comp_whiskerRight being child fields
Jad Ghalayini (Jan 23 2025 at 21:42):
But for example this code for the Drinfield center fails to synthesize (runs out of heartbeats) without the sorries
instance : MonoidalCategory (Center C) where
tensorObj X Y := tensorObj X Y
tensorHom f g := tensorHom f g
tensorHom_def := by intros; ext; simp [tensorHom_def]
whiskerLeft X _ _ f := whiskerLeft X f
whiskerRight f Y := whiskerRight f Y
tensorUnit := tensorUnit
associator := associator
leftUnitor := leftUnitor
rightUnitor := rightUnitor
whiskerLeft_comp := sorry
comp_whiskerRight := sorry
Jad Ghalayini (Jan 23 2025 at 21:42):
So my current approach is just to replace this with MonoidalCategory.mk'
, which of course makes the syntax a bit uglier since now all these things become named args with lambdas (thankfully can still use aesop cat as a default tactic)
Jad Ghalayini (Jan 23 2025 at 21:43):
Thing is only 4 things fail this way so it's not too irritating a change to just get it over with
Jad Ghalayini (Jan 23 2025 at 21:44):
The alternative is to copy Discretion
and have IsPremonoidal
and IsMonoidal
typeclasses
Jad Ghalayini (Jan 23 2025 at 21:44):
This would solve the problem since PremonoidalCategory
and MonoidalCategory
can just inherit from the appropriate typeclasses, and we can have an instance deriving IsPremonoidal
from IsMonoidal
Joël Riou (Jan 23 2025 at 21:45):
Why not keep MonoidalCategory
as it is, and only introduce IsBinoidal
and IsPremonoidal
?
Jad Ghalayini (Jan 23 2025 at 21:46):
That's what I do in discretion
Jad Ghalayini (Jan 23 2025 at 21:46):
This is ugly because it makes premonoidal categories into a second-class citizen, imo
Jad Ghalayini (Jan 23 2025 at 21:46):
Since now you write [Category C] [MonoidalCategoryStruct C] [IsPremonoidal C] everywhere
Jad Ghalayini (Jan 23 2025 at 21:47):
Of course, we could have a utility class [PremonoidalCategory C] which inherits from MonoidalCategoryStruct C and IsPremonoidal C and use that...
Jad Ghalayini (Jan 23 2025 at 21:48):
Also when you're actually doing these proofs you often want to do it in stages, e.g. first prove your category is binoidal, then use that to prove your category is premonoidal, etc
Joël Riou (Jan 23 2025 at 21:49):
Currently, we mostly have only MonoidalCategory
, and turning this into [MonoidalCategoryStruct C]
and [IsMonoidal C]
everywhere would be strictly more ugly...
Jad Ghalayini (Jan 23 2025 at 21:49):
No I specifically want to avoid this by having PremonoidalCategory C be a subclass of MonoidalCategory C
Jad Ghalayini (Jan 23 2025 at 21:50):
This also lets you prove a premonoidal category is monoidal by showing everything is central, which is nice
Jad Ghalayini (Jan 23 2025 at 21:50):
There is one nice alternative I've experimented with in discretion
quite a bit, but I have no idea why it doesn't seem to be used a lot in Mathlib which makes me fear there's something horribly wrong with it
Jad Ghalayini (Jan 23 2025 at 21:50):
That is: have a structure class (so MonoidalCategoryStruct)
Jad Ghalayini (Jan 23 2025 at 21:50):
A bunch of prop classes on it (IsPremonoidal, IsMonoidal, etc.)
Jad Ghalayini (Jan 23 2025 at 21:51):
and then define MonoidalCategory to inherit from IsMonoidal and MCS, PremonoidalCategory from IsPremonoidal and MCS, etc
Jad Ghalayini (Jan 23 2025 at 21:51):
The you can add an instance so that any MCS which is IsMonoidal is automatically a MonoidalCategory
Jad Ghalayini (Jan 23 2025 at 21:54):
I think I'm overcomplicating it and should just go with the custom constructor for now, I just wish there was nicer syntax/the default fields worked because then I wouldn't need the custom constructor and everything would be fine!
Jad Ghalayini (Jan 23 2025 at 22:13):
I do wonder why this is not working though:
class MonoidalCategory (C : Type u) [𝒞 : Category.{v} C] extends PremonoidalCategory C where
/--
Composition of tensor products is tensor product of compositions:
`(f₁ ⊗ g₁) ∘ (f₂ ⊗ g₂) = (f₁ ∘ f₂) ⊗ (g₁ ⊗ g₂)`
-/
tensor_comp :
∀ {X₁ Y₁ Z₁ X₂ Y₂ Z₂ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (g₁ : Y₁ ⟶ Z₁) (g₂ : Y₂ ⟶ Z₂),
(f₁ ≫ g₁) ⊗ (f₂ ≫ g₂) = (f₁ ⊗ f₂) ≫ (g₁ ⊗ g₂) := by
aesop_cat
whiskerLeft_comp := whiskerLeft_comp_ofTensorHom tensorHom_def id_whiskerRight tensor_comp
comp_whiskerRight := comp_whiskerRight_ofTensorHom tensorHom_def whiskerLeft_id tensor_comp
abbrev MonoidalCategory.mk' {C : Type u} [𝒞 : Category.{v} C] [MonoidalCategoryStruct C]
(tensorHom_def :
∀{X₁ Y₁ X₂ Y₂ : C} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂),
f ⊗ g = f ▷ X₂ ≫ Y₁ ◁ g := by aesop_cat)
(tensor_comp :
∀ {X₁ Y₁ Z₁ X₂ Y₂ Z₂ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (g₁ : Y₁ ⟶ Z₁) (g₂ : Y₂ ⟶ Z₂),
(f₁ ≫ g₁) ⊗ (f₂ ≫ g₂) = (f₁ ⊗ f₂) ≫ (g₁ ⊗ g₂) := by aesop_cat)
(whiskerLeft_id :
∀ (X Y : C), X ◁ 𝟙 Y = 𝟙 (X ⊗ Y) := by aesop_cat)
(id_whiskerRight :
∀ (X Y : C), 𝟙 X ▷ Y = 𝟙 (X ⊗ Y) := by aesop_cat)
(associator_naturality :
∀ {X₁ X₂ X₃ Y₁ Y₂ Y₃ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (f₃ : X₃ ⟶ Y₃),
((f₁ ⊗ f₂) ⊗ f₃) ≫ (α_ Y₁ Y₂ Y₃).hom = (α_ X₁ X₂ X₃).hom ≫ (f₁ ⊗ (f₂ ⊗ f₃))
:= by aesop_cat)
(leftUnitor_naturality :
∀ {X Y : C} (f : X ⟶ Y), 𝟙_ _ ◁ f ≫ (λ_ Y).hom = (λ_ X).hom ≫ f := by
aesop_cat)
(rightUnitor_naturality :
∀ {X Y : C} (f : X ⟶ Y), f ▷ 𝟙_ _ ≫ (ρ_ Y).hom = (ρ_ X).hom ≫ f := by
aesop_cat)
(pentagon :
∀ W X Y Z : C,
(α_ W X Y).hom ▷ Z ≫ (α_ W (X ⊗ Y) Z).hom ≫ W ◁ (α_ X Y Z).hom =
(α_ (W ⊗ X) Y Z).hom ≫ (α_ W X (Y ⊗ Z)).hom := by
aesop_cat)
(triangle :
∀ X Y : C, (α_ X (𝟙_ _) Y).hom ≫ X ◁ (λ_ Y).hom = (ρ_ X).hom ▷ Y := by
aesop_cat)
: MonoidalCategory C where
tensorHom_def := tensorHom_def
tensor_comp := tensor_comp
whiskerLeft_id := whiskerLeft_id
id_whiskerRight := id_whiskerRight
associator_naturality := associator_naturality
leftUnitor_naturality := leftUnitor_naturality
rightUnitor_naturality := rightUnitor_naturality
pentagon := pentagon
triangle := triangle
fails with "could not synthesize default value for field 'whiskerLeft_comp' of 'CategoryTheory.BinoidalCategory' using tactics" rather than just using the default value I gave it
Yuma Mizuno (Jan 23 2025 at 22:26):
Jad Ghalayini said:
No, but I just realized that I forgot to make the associators themselves central, d'uh...
Sorry for going back to my previous question. There is another possible definition of tensorHom
(rtimes
in discretion
). Does the rtimes
version associator_naturality_rtimes
hold as well? I think that should be the case, but I can't be sure right now.
Yuma Mizuno (Jan 23 2025 at 22:27):
Also, all possible mix verseions of the two.
Jad Ghalayini (Jan 23 2025 at 22:27):
Yuma Mizuno said:
Jad Ghalayini said:
No, but I just realized that I forgot to make the associators themselves central, d'uh...
Sorry for going back to my previous question. There is another possible definition of
tensorHom
(rtimes
indiscretion
). Does thertimes
versionassociator_naturality_rtimes
hold as well? I think that should be the case, but I can't be sure right now.
Yes, I'm using ltimes since that's what you guys currently use
Jad Ghalayini (Jan 23 2025 at 22:27):
Note that you can prove the rtimes version from the ltimes version of naturality and vice versa
Jad Ghalayini (Jan 23 2025 at 22:28):
In discretion we only assume the ltimes version and prove the rtimes version as a theorem
Yuma Mizuno (Jan 23 2025 at 22:28):
Can I see the proofs?
Jad Ghalayini (Jan 23 2025 at 22:30):
So in discretion
we define premonoidal categories as follows:
class IsBinoidal (C: Type u) [Category C] [MonoidalCategoryStruct C] : Prop where
tensorHom_def {X₁ Y₁ X₂ Y₂ : C} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂) :
f ⊗ g = (f ▷ X₂) ≫ (Y₁ ◁ g) := by
aesop_cat
whiskerLeft_id : ∀ (X Y : C), X ◁ 𝟙 Y = 𝟙 (X ⊗ Y) := by
aesop_cat
id_whiskerRight : ∀ (X Y : C), 𝟙 X ▷ Y = 𝟙 (X ⊗ Y) := by
aesop_cat
whiskerLeft_comp : ∀ {X Y Z W : C} (f : X ⟶ Y) (g : Y ⟶ Z), W ◁ (f ≫ g) = (W ◁ f) ≫ (W ◁ g)
:= by aesop_cat
whiskerRight_comp : ∀ {X Y Z W : C} (f : X ⟶ Y) (g : Y ⟶ Z), (f ≫ g) ▷ W = (f ▷ W) ≫ (g ▷ W)
:= by aesop_cat
class IsPremonoidal (C: Type u) [Category C] [MonoidalCategoryStruct C]
extends IsBinoidal C : Prop where
associator_central : ∀ {X Y Z : C}, Monoidal.Central (α_ X Y Z).hom := by aesop_cat
leftUnitor_central : ∀ {X : C}, Monoidal.Central (λ_ X).hom := by aesop_cat
rightUnitor_central : ∀ {X : C}, Monoidal.Central (ρ_ X).hom := by aesop_cat
/-- Naturality of the associator isomorphism: `(f₁ ⊗ f₂) ⊗ f₃ ≃ f₁ ⊗ (f₂ ⊗ f₃)` -/
associator_naturality :
∀ {X₁ X₂ X₃ Y₁ Y₂ Y₃ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (f₃ : X₃ ⟶ Y₃),
((f₁ ⊗ f₂) ⊗ f₃) ≫ (α_ Y₁ Y₂ Y₃).hom = (α_ X₁ X₂ X₃).hom ≫ (f₁ ⊗ (f₂ ⊗ f₃)) := by
aesop_cat
/--
Naturality of the left unitor, commutativity of `𝟙_ C ⊗ X ⟶ 𝟙_ C ⊗ Y ⟶ Y` and `𝟙_ C ⊗ X ⟶ X ⟶ Y`
-/
leftUnitor_naturality :
∀ {X Y : C} (f : X ⟶ Y), 𝟙_ _ ◁ f ≫ (λ_ Y).hom = (λ_ X).hom ≫ f := by
aesop_cat
/--
Naturality of the right unitor: commutativity of `X ⊗ 𝟙_ C ⟶ Y ⊗ 𝟙_ C ⟶ Y` and `X ⊗ 𝟙_ C ⟶ X ⟶ Y`
-/
rightUnitor_naturality :
∀ {X Y : C} (f : X ⟶ Y), f ▷ 𝟙_ _ ≫ (ρ_ Y).hom = (ρ_ X).hom ≫ f := by
aesop_cat
/--
The pentagon identity relating the isomorphism between `X ⊗ (Y ⊗ (Z ⊗ W))` and `((X ⊗ Y) ⊗ Z) ⊗ W`
-/
pentagon :
∀ W X Y Z : C,
(α_ W X Y).hom ▷ Z ≫ (α_ W (X ⊗ Y) Z).hom ≫ W ◁ (α_ X Y Z).hom =
(α_ (W ⊗ X) Y Z).hom ≫ (α_ W X (Y ⊗ Z)).hom := by
aesop_cat
/--
The identity relating the isomorphisms between `X ⊗ (𝟙_ C ⊗ Y)`, `(X ⊗ 𝟙_ C) ⊗ Y` and `X ⊗ Y`
-/
triangle :
∀ X Y : C, (α_ X (𝟙_ _) Y).hom ≫ X ◁ (λ_ Y).hom = (ρ_ X).hom ▷ Y := by
aesop_cat
Note we assume that ⊗ = ⋉
by tensorHom_def
Jad Ghalayini (Jan 23 2025 at 22:31):
It's trivial to prove left/middle/right versions from this as follows:
theorem associator_naturality {X₁ X₂ X₃ Y₁ Y₂ Y₃ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (f₃ : X₃ ⟶ Y₃) :
((f₁ ⊗ f₂) ⊗ f₃) ≫ (α_ Y₁ Y₂ Y₃).hom = (α_ X₁ X₂ X₃).hom ≫ (f₁ ⊗ (f₂ ⊗ f₃))
:= IsPremonoidal.associator_naturality f₁ f₂ f₃
@[reassoc]
theorem associator_naturality_right {X Y Z : C} (f : X ⟶ X') :
(f ▷ Y) ▷ Z ≫ (α_ X' Y Z).hom = (α_ X Y Z).hom ≫ f ▷ (Y ⊗ Z) := by
convert associator_naturality f (𝟙 Y) (𝟙 Z) using 1 <;> simp [tensorHom_def]
@[reassoc]
theorem associator_naturality_middle {X Y Z : C} (f : Y ⟶ Y') :
(X ◁ f) ▷ Z ≫ (α_ X Y' Z).hom = (α_ X Y Z).hom ≫ X ◁ (f ▷ Z) := by
convert associator_naturality (𝟙 _) f (𝟙 _) using 1 <;> simp [tensorHom_def]
@[reassoc]
theorem associator_naturality_left {X Y Z : C} (f : Z ⟶ Z') :
(X ⊗ Y) ◁ f ≫ (α_ X Y Z').hom = (α_ X Y Z).hom ≫ X ◁ (Y ◁ f) := by
convert associator_naturality (𝟙 _) (𝟙 _) f using 1 <;> simp [tensorHom_def]
@[reassoc]
theorem associator_inv_naturality
{X₁ X₂ X₃ Y₁ Y₂ Y₃ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (f₃ : X₃ ⟶ Y₃) :
(f₁ ⊗ (f₂ ⊗ f₃)) ≫ (α_ Y₁ Y₂ Y₃).inv = (α_ X₁ X₂ X₃).inv ≫ ((f₁ ⊗ f₂) ⊗ f₃)
:= (cancel_mono (α_ Y₁ Y₂ Y₃).hom).mp (by simp [associator_naturality])
@[reassoc]
theorem associator_inv_naturality_right {X Y Z : C} (f : X ⟶ X') :
f ▷ (Y ⊗ Z) ≫ (α_ X' Y Z).inv = (α_ X Y Z).inv ≫ f ▷ Y ▷ Z := by
convert associator_inv_naturality f (𝟙 _) (𝟙 _) using 1 <;> simp [tensorHom_def]
@[reassoc]
theorem associator_inv_naturality_middle {X Y Z : C} (f : Y ⟶ Y') :
X ◁ (f ▷ Z) ≫ (α_ X Y' Z).inv = (α_ X Y Z).inv ≫ (X ◁ f) ▷ Z := by
convert associator_inv_naturality (𝟙 _) f (𝟙 _) using 1 <;> simp [tensorHom_def]
@[reassoc]
theorem associator_inv_naturality_left {X Y Z : C} (f : Z ⟶ Z') :
X ◁ (Y ◁ f) ≫ (α_ X Y Z').inv = (α_ X Y Z).inv ≫ (X ⊗ Y) ◁ f := by
convert associator_inv_naturality (𝟙 _) (𝟙 _) f using 1 <;> simp [tensorHom_def]
@[reassoc]
theorem leftUnitor_naturality {X Y : C} (f : X ⟶ Y) :
𝟙_ C ◁ f ≫ (λ_ Y).hom = (λ_ X).hom ≫ f := IsPremonoidal.leftUnitor_naturality f
@[reassoc]
theorem leftUnitor_inv_naturality {X Y : C} (f : X ⟶ Y) :
f ≫ (λ_ Y).inv = (λ_ X).inv ≫ 𝟙_C ◁ f := by
apply (cancel_mono (λ_ Y).hom).mp
simp [leftUnitor_naturality]
@[reassoc]
theorem rightUnitor_naturality {X Y : C} (f : X ⟶ Y) :
f ▷ 𝟙_ C ≫ (ρ_ Y).hom = (ρ_ X).hom ≫ f := IsPremonoidal.rightUnitor_naturality f
@[reassoc]
theorem rightUnitor_inv_naturality {X Y : C} (f : X ⟶ Y) :
f ≫ (ρ_ Y).inv = (ρ_ X).inv ≫ f ▷ 𝟙_ C := by
apply (cancel_mono (ρ_ Y).hom).mp
simp [rightUnitor_naturality]
Jad Ghalayini (Jan 23 2025 at 22:33):
I didn't bother writing versions for rtimes, but you can see that e.g. for associators if I wanted to do naturality for
I'd rewrite it to
and apply right, middle, left naturality lemmas to get
I can do the same for any permutation of f, g, h
Jad Ghalayini (Jan 23 2025 at 22:35):
In fact, premonoidal categories are usually defined with separate naturality squares for the left, right, and middle; I'm just being lazy and noting that you can instead equivalently just write a single square with ltimes and derive these, and you just happen to get the same thing originally in MonoidalCategory
Yuma Mizuno (Jan 23 2025 at 22:35):
I see, thanks!
Yuma Mizuno (Jan 23 2025 at 22:38):
Jad Ghalayini said:
(indeed it is standard notation to write central morphisms with tensors and everything else with ltimes/rtimes)
I actually prefer this convension, which is less confusing for me.
Jad Ghalayini (Jan 23 2025 at 22:39):
Yuma Mizuno said:
Jad Ghalayini said:
(indeed it is standard notation to write central morphisms with tensors and everything else with ltimes/rtimes)
I actually prefer this convension, which is less confusing for me.
As in, writing central morphisms with tensors? I agree; all other use of tensors in discretion
is for backwards compatibility purposes with mathlib's monoidal stuff
Jad Ghalayini (Jan 23 2025 at 22:47):
Also, I'm currently experimenting with a design like this to deal with the default member problem. Would such dirty hacks be acceptable as a pure implementation detail, assuming the rest of mathlib can use MonoidalCategory
with exactly the same API as before?
variable (C : Type u) [𝒞 : Category.{v} C] [MonoidalCategoryStruct C]
class TensorHomDef : Prop where
tensorHom_def {X₁ Y₁ X₂ Y₂ : C} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂) :
f ⊗ g = (f ▷ X₂) ≫ (Y₁ ◁ g) := by aesop_cat
class WhiskeringId : Prop where
/- Left whiskering of the identity is the identity: `X ◁ 𝟙 Y = 𝟙 (X ⊗ Y)` -/
whiskerLeft_id : ∀ (X Y : C), X ◁ 𝟙 Y = 𝟙 (X ⊗ Y) := by
aesop_cat
/- Right whiskering of the identity is the identity `𝟙 X ▷ Y = 𝟙 (X ⊗ Y)` -/
id_whiskerRight : ∀ (X Y : C), 𝟙 X ▷ Y = 𝟙 (X ⊗ Y) := by
aesop_cat
class WhiskeringComp : Prop where
/- Left whiskering respects composition -/
whiskerLeft_comp (W : C) {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) :
W ◁ (f ≫ g) = W ◁ f ≫ W ◁ g := by
aesop_cat
/- Right whiskering respects composition -/
comp_whiskerRight {W X Y : C} (f : W ⟶ X) (g : X ⟶ Y) (Z : C) :
(f ≫ g) ▷ Z = f ▷ Z ≫ g ▷ Z := by
aesop_cat
class TensorFunctorial : Prop where
/-- Tensor product of identity maps is the identity: `(𝟙 X₁ ⊗ 𝟙 X₂) = 𝟙 (X₁ ⊗ X₂)` -/
tensor_id : ∀ X₁ X₂ : C, 𝟙 X₁ ⊗ 𝟙 X₂ = 𝟙 (X₁ ⊗ X₂) := by
aesop_cat
/--
Composition of tensor products is tensor product of compositions:
`(f₁ ⊗ g₁) ∘ (f₂ ⊗ g₂) = (f₁ ∘ f₂) ⊗ (g₁ ⊗ g₂)`
-/
tensor_comp :
∀ {X₁ Y₁ Z₁ X₂ Y₂ Z₂ : C} (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (g₁ : Y₁ ⟶ Z₁) (g₂ : Y₂ ⟶ Z₂),
(f₁ ≫ g₁) ⊗ (f₂ ≫ g₂) = (f₁ ⊗ f₂) ≫ (g₁ ⊗ g₂) := by
aesop_cat
theorem WhiskeringId.id_tensorHom [TensorHomDef C] [WhiskeringId C]
(X : C) {Y₁ Y₂ : C} (f : Y₁ ⟶ Y₂) :
𝟙 X ⊗ f = X ◁ f := by simp [TensorHomDef.tensorHom_def, id_whiskerRight]
theorem WhiskeringId.tensorHom_id [TensorHomDef C] [WhiskeringId C]
{X₁ X₂ : C} (f : X₁ ⟶ X₂) (Y : C) :
f ⊗ 𝟙 Y = f ▷ Y := by simp [TensorHomDef.tensorHom_def, whiskerLeft_id]
instance TensorFunctorial.instWhiskeringComp
[TensorHomDef C] [TensorFunctorial C] [WhiskeringId C] : WhiskeringComp C where
whiskerLeft_comp := by intros; simp [<-WhiskeringId.id_tensorHom, <-tensor_comp]
comp_whiskerRight := by intros; simp [<-WhiskeringId.tensorHom_id, <-tensor_comp]
Jad Ghalayini (Jan 23 2025 at 22:47):
Note that now the WhiskeringComp fields are automatically generated by typeclass inference
Jad Ghalayini (Jan 23 2025 at 22:48):
I'm taking inspiration from how Lattice
and friends work; the idea would be to have BinoidalCategory
extend WhiskeringId, WhiskeringComp
, and TensorHomDef
while MonoidalCategory
would extend TensorFunctorial
Jad Ghalayini (Jan 23 2025 at 22:49):
TensorFunctorial
would also by typeclass inference render everything central, and hence it would be easy to infer the associators are central by e.g. just infer_instance
Jad Ghalayini (Jan 23 2025 at 22:50):
In general I'd like to separate out the tensor structure (whiskering, homs, etc) from the monoidal structure (associators) but that can be a separate PR, again, most users would see no difference except that you can theoretically structure your proofs a bit more cleanly by using the fact that your category is binoidal before even constructing associators
Jad Ghalayini (Jan 23 2025 at 22:51):
This is however only really useful for my use-case where (in the repo https://github.com/imbrem/debruijn-ssa) I construct a premonoidal category by quotienting syntax and defining associators/unitors/etc is Very Hard (TM), with the binoidal structure maybe useful to prove e.g. the associator is an isomorphism
Jad Ghalayini (Jan 24 2025 at 16:53):
I've been facing some issues with default members, which have been moved to #lean4 > Issues with default parameters . My current best-effort solution is just to fill in the default parameters for all uses of MonoidalCategory
now, since when/if that issue is fixed we can remove them. Other options include:
- Leaving them in
- Weird typeclass hack I've been experimenting with to avoid this problem, but it messes with the
monoidal
tactic
Yuma Mizuno (Jan 25 2025 at 12:28):
I would like to suggest using whisker_exchange
rather than tensor_comp
as an axiom for MonoidalCategory
minus PremonoidalCategory
. Adding a redundant condition is aesthetically unappealing (in my personal view) and may increase the work when proving the condition in practice.
We can define an additional constructor for MonoidalCategory
that includes tensor_comp
as an axiom, written solely in terms of tensorHom
rather than whiskerings. Several monoidal category instances in the current downstream files could likely be given by this constructor.
Jad Ghalayini (Jan 26 2025 at 14:40):
@Yuma Mizuno I could do that, but that would require changing all existing instances of MonoidalCategory
to use the new constructor. On the other hand, it would unblock us from #lean4 > Issues with default parameters , and the other solution I was considering is kind of ugly. Would doing this be acceptable, that is, changing every
instance : MonoidalCategory C where
tensor_comp f g := ...
to
instance: MonoidalCategory C := MonoidalCategory.mk' (tensor_comp := fun f g => ...)
Jad Ghalayini (Jan 26 2025 at 14:41):
If so I can probably get a PR ready Soon (TM) (I was really gunning for yesterday but I used the whole day on it and I have to give a presentation tomorrow rip)
Jad Ghalayini (Jan 26 2025 at 14:42):
Also w.r.t. your note about work it turns out the automation is much better at proving things like tensor_comp
than it is at proving things like whiskerLeft_comp
, let alone whisker_exchange
. This actually makes sense when you consider the current simp
-normal forms favored, and I don't plan to change that since most math people will be using monoidal categories, and PL users such as myself will need weird simplifications anyways
Jad Ghalayini (Jan 26 2025 at 14:43):
(At least, so my intuition tells me from work on discretion
)
Joël Riou (Jan 26 2025 at 15:51):
If the lean4 issue has a chance to be solved in a near future, I would prefer we wait for the fix, unless there are other particular reasons to proceed very fast.
Yuma Mizuno (Jan 26 2025 at 16:06):
Jad Ghalayini said:
Would doing this be acceptable, that is, changing every
instance : MonoidalCategory C where tensor_comp f g := ...
to
instance: MonoidalCategory C := MonoidalCategory.mk' (tensor_comp := fun f g => ...)
In my opinion, this kind of change is acceptable. The default constructor has some syntactic privileges, but other than that I think the change is not large.
Yuma Mizuno (Jan 26 2025 at 16:07):
Perhaps the syntax could be improved by defining a structure that contains the arguments of the additional constructor?
Jad Ghalayini (Jan 26 2025 at 23:28):
@Joël Riou if we go with the whisker_exchange
design then things look the same whether or not we have the fix, hence my suggestion to just go ahead. On the other hand, with tensor_comp
, things are indeed a _lot_ cleaner with the fix.
Yuma Mizuno (Jan 27 2025 at 08:00):
Jad Ghalayini said:
Also w.r.t. your note about work it turns out the automation is much better at proving things like
tensor_comp
than it is at proving things likewhiskerLeft_comp
, let alonewhisker_exchange
.
I find this observation interesting since it contradicts my intuition. I would like to know more about this.
One note: It is "intentional" that the simp automation does not handle whisker_exchange
. Currently, simp
does not determine whether right or left morphisms should come first. On the other hand, I believe the automation works well for whiskerLeft_comp
. It just expands the expression distributively, which is a typical simp lemma in algebraic theories.
Jad Ghalayini (Feb 05 2025 at 18:56):
@Yuma Mizuno so I finally found some time to work on this again, and I'm nearly finished what will hopefully be a decent PR
Jad Ghalayini (Feb 05 2025 at 18:56):
I've got a question though: for stuff that's true for PremonoidalCategory, should we move it from the MonoidalCategory namespace to the PremonoidalCategory namespace and re-export it or just leave it in the MonoidalCategory namespace with a PremonoidalCategory bound?
Jad Ghalayini (Feb 05 2025 at 19:00):
Going with the former so far
Jad Ghalayini (Feb 05 2025 at 19:28):
One issue I'm worried about however is the notation is in MonoidalCategory, so we'd want to open that anyways...
Jad Ghalayini (Feb 06 2025 at 01:35):
OK, I'm done a draft PR:
https://github.com/leanprover-community/mathlib4/pull/21488
Jad Ghalayini (Feb 06 2025 at 16:18):
I'm stuck because this change seems to break the string diagram tool...
Jad Ghalayini (Feb 06 2025 at 16:19):
@Yuma Mizuno this seems to be related to the coherence tactic; mind helping me out?
Jad Ghalayini (Feb 06 2025 at 16:20):
I have no idea how CoherenceM
works
Jad Ghalayini (Feb 06 2025 at 18:35):
I fixed the failing tests with type hints, should have thought of that first!
Jad Ghalayini (Feb 06 2025 at 18:35):
Well, at least I hope I did, waiting for CI!
Yuma Mizuno (Feb 07 2025 at 18:25):
Thanks! I can't look it in detail today, but I will sometime soon.
Jad Ghalayini (Feb 08 2025 at 14:23):
Thanks a lot! I've now got the monoidal_coherence
tactic working, and the monoidal
tactic working _sometimes_, since premonoidal categories can't interconvert between f \rtimes g
and f \otimes g
. We'd probably want a premonoidal
tactic that doesn't attempt such normalization, but for now we just error out if its required with a can't find monoidal instance
and that works just fine
Jad Ghalayini (Feb 19 2025 at 12:05):
Hello! I realize this PR is very big; do you think it would be worthwhile to split it into some smaller PRs which:
- Introduce the premonoidal category API
- Port the
coherence
tactic to use the premonoidal category API (depends on 1) - Port braided + symmetric monoidal categories to use premonoidal categories (depends on 2)
- Add some extra lemmas unique to premonoidal categories (depends on 1)
Jad Ghalayini (Feb 19 2025 at 12:05):
@Yuma Mizuno ?
Kim Morrison (Feb 19 2025 at 12:10):
Sorry I'm coming to this very late. I admit I am a little skeptical, and would like to see some more explanation of why premonoidal categories are a natural concept (despite working in low-dimensional category theory for many years, I had not met them).
In particular, consider the following question: what if someone later wants to add the (in my mind, better justified) definition of a skew monoidal category (this is one in which the associator is not necessarily invertible). How will the development of monoidal categories look then, if it has to accomodate both? Would it still be viable?
Kim Morrison (Feb 19 2025 at 12:11):
(I can't promise to engage at length with an answer here --- but I hope whoever is reviewing these PRs considers the question/answer!)
Jad Ghalayini (Feb 19 2025 at 13:24):
Kim Morrison said:
Sorry I'm coming to this very late. I admit I am a little skeptical, and would like to see some more explanation of why premonoidal categories are a natural concept (despite working in low-dimensional category theory for many years, I had not met them).
In particular, consider the following question: what if someone later wants to add the (in my mind, better justified) definition of a skew monoidal category (this is one in which the associator is not necessarily invertible). How will the development of monoidal categories look then, if it has to accomodate both? Would it still be viable?
So premonoidal categories are an extremely natural concept in theoretical computer science, since they (very slightly) generalize the Kleisli category of a strong monad over a symmetric monoidal category
Jad Ghalayini (Feb 19 2025 at 13:25):
I specifically need them to formalize my PhD thesis, which is about using premonoidal categories to model refinement of imperative programs in a variety of complex memory models
Jad Ghalayini (Feb 19 2025 at 13:26):
I can't think of _too many_ uses in pure mathematics off the top of my head
Jad Ghalayini (Feb 19 2025 at 13:26):
Skew monoidal categories would be imo no more difficult to implement than they are now, since you'd need to change MonoidalCategoryStruct
to not make the associator an isomorphism either way
Jad Ghalayini (Feb 19 2025 at 13:27):
One particularly important CS-flavored application is https://ncatlab.org/nlab/show/Freyd+category, and in particular a lot of axiomatic domain theory, as well as modeling Lawvere theories
Jad Ghalayini (Feb 19 2025 at 13:30):
Right now in my library discretion
I've got a dirty hack where I essentially copy over the monoidal category implementation as PremonoidalCategory
, and it's... not very pretty; I'd much rather just use it from Mathlib and not have to duplicate all that + the tactics
Jad Ghalayini (Feb 19 2025 at 13:32):
Jad Ghalayini said:
Kim Morrison said:
Sorry I'm coming to this very late. I admit I am a little skeptical, and would like to see some more explanation of why premonoidal categories are a natural concept (despite working in low-dimensional category theory for many years, I had not met them).
In particular, consider the following question: what if someone later wants to add the (in my mind, better justified) definition of a skew monoidal category (this is one in which the associator is not necessarily invertible). How will the development of monoidal categories look then, if it has to accomodate both? Would it still be viable?
So premonoidal categories are an extremely natural concept in theoretical computer science, since they (very slightly) generalize the Kleisli category of a strong monad over a symmetric monoidal category
My longer-term hopes would be to have a large amount of rewriting for monads over arbitrary SMCs (and in particular, for my thesis, the category of partial orders) done in terms of premonoidal categories, and then separately theorems about commutative monads and how, if a monad is commutative, its Kleisli category is in fact monoidal
Jad Ghalayini (Feb 19 2025 at 13:34):
Lots of interesting things can be written as strong monads over the appropriate category, so hopefully that should open some math applications too other than the extensive theoretical CS applications (in particular, for example, the fact that the free vector space monad is commutative derives a lot of linear algebra in a slick way; on the other hand, the free module monad is not necessarily commutative, and hence induces a premonoidal rather than monoidal category)
Yuma Mizuno (Feb 19 2025 at 15:46):
Based on Kim's comments, I'd like to review these changes more carefully.
Jad Ghalayini said:
Hello! I realize this PR is very big; do you think it would be worthwhile to split it into some smaller PRs which:
In any case, I think the split of the PR would be better in this PR process. As step zero, would it be possible to first separate the following?: Before introducing Premonoidal, rewrite the definition of monoidal in terms of whiskering and introduce the constructor ofTensorHom
.
Regarding introducing of Premonoidal category, my perspective might be based on the following my experience: I previously attempted the above "step zero" as a part of a refactoring of the monoidal category library (though I didn't complete it as it wasn't really necessary at the time). I believe the split of whisker_exchange
by introducing Premonoidal category could be done without much effort during that process. While this itself doesn't demonstrate necessity of Premonoidal category definition, it might explain why I am less skepitical to it.
Also, for the split of PRs, would it be possible to postpone the introduction of ltimes and rtimes operators to a later step? To be honest, I'm not yet clear about their need at this point.
(I can't see mathlib this week as I'm traveling without my main PC, sorry about that.)
Jad Ghalayini (Feb 19 2025 at 19:18):
Yuma Mizuno said:
Based on Kim's comments, I'd like to review these changes more carefully.
Jad Ghalayini said:
Hello! I realize this PR is very big; do you think it would be worthwhile to split it into some smaller PRs which:
In any case, I think the split of the PR would be better in this PR process. As step zero, would it be possible to first separate the following?: Before introducing Premonoidal, rewrite the definition of monoidal in terms of whiskering and introduce the constructor
ofTensorHom
.Regarding introducing of Premonoidal category, my perspective might be based on the following my experience: I previously attempted the above "step zero" as a part of a refactoring of the monoidal category library (though I didn't complete it as it wasn't really necessary at the time). I believe the split of
whisker_exchange
by introducing Premonoidal category could be done without much effort during that process. While this itself doesn't demonstrate necessity of Premonoidal category definition, it might explain why I am less skepitical to it.Also, for the split of PRs, would it be possible to postpone the introduction of ltimes and rtimes operators to a later step? To be honest, I'm not yet clear about their need at this point.
(I can't see mathlib this week as I'm traveling without my main PC, sorry about that.)
OK, that works, though I might need a bit of time as I have a paper deadline coming up
Jad Ghalayini (Feb 19 2025 at 19:18):
I can leave ltimes and rtimes out, but really I just view them as syntax sugar for writing down centrality more cleanly, rather than anything fundamental (they're just an abbrev in my PR). Would it be a big add to have them as scoped notation inside PremonoidalCategory
?
Jad Ghalayini (Apr 07 2025 at 12:22):
Since https://github.com/leanprover/lean4/issues/6769 was just merged, do we still want to refactor the MonoidalCategory
instances to use the ofTensorHom
constructor or should we use default parameters?
Jad Ghalayini (Apr 07 2025 at 12:22):
I've fixed the merge conflicts, just making sure everything builds (I'm away from home on a tiny laptop, so slow!) before pushing
Jad Ghalayini (Apr 07 2025 at 12:23):
But if I'll need to split up the PR anyways was wondering whether I should try the default parameter approach or whether using the ofTensorHom
constructor is strictly better
Jad Ghalayini (Apr 07 2025 at 12:23):
Sorry for the inactivity, Thesis Is Hard (TM)
Yuma Mizuno (Apr 08 2025 at 20:03):
My preference is to use ofTensorHom
, not to use tensorHom
in PremonoidalCategory
. My mental model of tensorHom
is horizontally aligned morphisms in a string diagram, which I think is meaningful interpretation only in MonoidalCategory
. So what I really expect is like
PremonoidalCategoryStruct
• left whiskering
• right whiskering
PremonoidalCategory extends PremonoidalCategoryStruct
• axioms
MonoidalCategoryStruct extends PremonoidalCategoryStruct
• tensorHom
MonoidalCategory extends PremonoidalCategory, MonoidalCategoryStruct
• whiskering_exchange
• tensorHom_def
Yuma Mizuno (Apr 08 2025 at 20:06):
Also, I don't think it's a good idea to have a long list of exports, as it hard to maintain. How about basically having the MonoidalCategory
namespace even if theorems hold in Premonoidal categories?
Kevin Buzzard (Apr 08 2025 at 20:46):
We have the RingHom namespace even though stuff applies to semirings
Last updated: May 02 2025 at 03:31 UTC