Zulip Chat Archive

Stream: mathlib4

Topic: diamond in CommAlgCat


Michał Mrugała (Mar 24 2025 at 17:52):

I'm trying to prove that a commutative Hopf algebra over R : CommRingCat defines an instance of a group object in (Under R)ᵒᵖ, but I consistently run into an issue with type class inference. To illustrate the issue let's try defining the multiplication morphism:

open CategoryTheory Opposite

variable {R : CommRingCat} {A : Type*} [CommRing A] [HopfAlgebra R A]

noncomputable instance : Grp_Class <| op <| CommRingCat.mkUnder R A where
  one := op <| (Bialgebra.counitAlgHom R A).toUnder
  mul := op <| by
    change R.mkUnder A  R.mkUnder _
    simp
    /-
    ⊢ R.mkUnder A ⟶ R.mkUnder (TensorProduct ↑R ↑(R.mkUnder A).right ↑(R.mkUnder A).right)
    -/
    refine (Bialgebra.comulAlgHom R A).toUnder
    sorry
  one_mul' := sorry
  mul_one' := sorry
  mul_assoc' := sorry
  inv := sorry
  left_inv' := sorry
  right_inv' := sorry

The refine fails due to a mismatch of the inferred typeclasses between Bialgebra.toAlgebra and (CommRingCat.instAlgebraCarrierRightDiscretePUnit (R.mkUnder A)). This can be solved by using the following:

noncomputable instance : Grp_Class <| op <| CommRingCat.mkUnder R A where
  one := op <| (Bialgebra.counitAlgHom R A).toUnder
  mul := op <| by
    refine (Bialgebra.comulAlgHom R A).toUnder  (Algebra.TensorProduct.map ?_ ?_).toUnder <;>
      exact @AlgHom.mk _ _ _ _ _ _ _ (_) (.id _) fun _  rfl

However, this typeclass issue keeps consistently popping up in this context. Is there a way to prevent this mismatch from happening?

Yaël Dillies (Mar 24 2025 at 18:27):

For readers with less context than me, docs#CommRingCat.instAlgebraCarrierRightDiscretePUnit is constructed out of docs#RingHom.toAlgebra, which is known to cause non-defeq diamonds (because it makes up the redundant smul field)

Yaël Dillies (Mar 24 2025 at 18:28):

Michał and I know why this mismatch is happening, so the question rather is: Can we design the code so as to avoid running into this mismatch?

Aaron Liu (Mar 24 2025 at 18:34):

Yaël Dillies said:

For readers with less context than me, docs#CommRingCat.instAlgebraCarrierRightDiscretePUnit is constructed out of docs#RingHom.toAlgebra, which is known to cause non-defeq diamonds (because it makes up the redundant nsmul, zsmul, etc... fields)

I don't see those fields in docs#Algebra. Am I missing something?

Yaël Dillies (Mar 24 2025 at 18:36):

Sorry, I only mean docs#Algebra.smul. Edited. Same issue though ;-)

Kevin Buzzard (Mar 24 2025 at 19:27):

Is this a #mwe ? After import Mathlib I get

failed to synthesize
  ChosenFiniteProducts (Under R)ᵒᵖ

Is this what you're asking about? (I doubt it)

Michał Mrugała (Mar 24 2025 at 19:34):

This is not a mwe because of this instance not being in mathlib. I can post the code later.

Kevin Buzzard (Mar 24 2025 at 19:35):

Probably you can illustrate the diamond without posting the chosen finite products instance.

Kevin Buzzard (Mar 24 2025 at 19:45):

Is this your question:

import Mathlib

variable {R : CommRingCat} {A : Type*} [CommRing A] [Algebra R A]

example : A = (CommRingCat.mkUnder R A) := rfl

def i1 : SMul R A := inferInstance
def i2 : SMul R (CommRingCat.mkUnder R A) := inferInstance

example (r : R) (a : A) : @SMul.smul R A i1 r a =  @SMul.smul R A i2 r a := rfl -- fails

? Yeah this is a common story in category theory, unfortunately. This sort of thing was the bane of Amelia's life when doing group cohomology.

Kevin Buzzard (Mar 24 2025 at 20:16):

As you say,

import Mathlib

variable {R : CommRingCat} {A : Type*} [CommRing A] [ia : Algebra R A]

example : A = (CommRingCat.mkUnder R A) := rfl

def i1 : SMul R A := inferInstance
def i2 : SMul R (CommRingCat.mkUnder R A) := inferInstance

example (r : R) (a : A) : @SMul.smul R A i1 r a =  @SMul.smul R A i2 r a := by
  change ia.1.1 r a = (algebraMap (R) A) r * a
  sorry -- not rfl

Michał Mrugała (Mar 24 2025 at 21:29):

This looks like the same issue essentially, and it’s the bane of my existence because it makes simplifying and rewriting expressions a nightmare.

Kevin Buzzard (Mar 25 2025 at 16:28):

Yeah there is a fundamental problem with our set-up here. I still can't run your actual code to the see the problem because you still didn't post a #mwe so it's difficult to help. What happens if you remove the instance tag from CommRingCat.instAlgebraCarrierRightDiscretePUnit?

Kevin Buzzard (Mar 25 2025 at 16:30):

You could also add something like instance [Algebra R A] : Algebra R ↑(CommRingCat.mkUnder R A) := inferInstanceAs (Algebra R A) or whatever the syntax for that is.

Michał Mrugała (Mar 25 2025 at 16:42):

Here is the code for a working example:

import Mathlib

open CategoryTheory Limits Opposite

namespace CategoryTheory.Limits
variable {C : Type*} [Category C] {X Y Z : C} {f : X  Y} {g : X  Z}

@[simp]
def pushoutCocone.toBinaryCofan : PushoutCocone f g  BinaryCofan (Under.mk f) (.mk g) where
  obj c := BinaryCofan.mk (Under.homMk (U := Under.mk f) c.inl rfl)
      (Under.homMk (U := Under.mk g) (V := Under.mk (f  c.inl)) c.inr c.condition.symm)
  map {c1 c2} a := {
    hom := Under.homMk a.hom
    w := by rintro (_|_) <;> aesop_cat
  }

@[simp]
def binaryCofanUnder.toPushoutCocone : BinaryCofan (Under.mk f) (.mk g)  PushoutCocone f g where
  obj c := PushoutCocone.mk c.inl.right c.inr.right (c.inl.w.symm.trans c.inr.w)
  map {c1 c2} a := {
    hom := a.hom.right
    w := by rintro (_|_|_) <;> simp [ Under.comp_right]
  }

def aux_unit :
    𝟭 (PushoutCocone f g)  pushoutCocone.toBinaryCofan  binaryCofanUnder.toPushoutCocone :=
  NatIso.ofComponents (fun c  c.eta) (by aesop_cat)

def aux_counit :
    binaryCofanUnder.toPushoutCocone  pushoutCocone.toBinaryCofan
     𝟭 (BinaryCofan (Under.mk f) (Under.mk g)) :=
  NatIso.ofComponents (fun X  Limits.BinaryCofan.ext (Under.isoMk (Iso.refl _)
    (by simpa using X.inl.w.symm)) (by aesop_cat) (by aesop_cat))
    (by intros; ext; simp [BinaryCofan.ext])

@[simp]
def pushoutCoconeEquivBinaryCofan : PushoutCocone f g  BinaryCofan (Under.mk f) (Under.mk g) :=
  .mk pushoutCocone.toBinaryCofan binaryCofanUnder.toPushoutCocone aux_unit aux_counit

def pushoutCocone.IsColimit.toBinaryCofanIsColimit {c : PushoutCocone f g}  (hc : IsColimit c) :
    IsColimit <| pushoutCocone.toBinaryCofan.obj c :=
  (IsColimit.ofCoconeEquiv pushoutCoconeEquivBinaryCofan).symm hc

end CategoryTheory.Limits

namespace CategoryTheory.Limits
variable {C : Type*} [Category C] {X Y P : C}

@[simps!]
def BinaryCofan.op (c : BinaryCofan X Y) : BinaryFan (.op X : Cᵒᵖ) (.op Y) :=
  .mk (.op c.inl) (.op c.inr)

@[simps!]
def BinaryFan.unop (c : BinaryFan (.op X : Cᵒᵖ) (.op Y)) : BinaryCofan X Y :=
  BinaryCofan.mk c.fst.unop c.snd.unop

@[simp] lemma BinaryCofan.op_mk (ι₁ : X  P) (ι₂ : Y  P) : op (mk ι₁ ι₂) = .mk ι₁.op ι₂.op := rfl

@[simp] lemma BinaryFan.unop_mk (ι₁ : op P  op X) (ι₂ : op P  op Y) :
    unop (mk ι₁ ι₂) = .mk ι₁.unop ι₂.unop := rfl

lemma aux {D : Type*} [Category D] {F G : C  D} (α : F  G) :
    (NatTrans.op α).app (.op X) = (α.app X).op := rfl

def BinaryCofan.IsColimit.op {c : BinaryCofan X Y} (hc : IsColimit c) : IsLimit <| c.op where
  lift s := .op <| hc.desc (BinaryFan.unop s)
  fac s := by rintro (_|_) <;> simp [ CategoryTheory.op_comp, hc.fac]
  uniq s m h := by
    replace h j : c.ι.app j  m.unop = (BinaryFan.unop s).ι.app j := by
      specialize h j; obtain ⟨_ | _⟩ := j <;> simpa using Quiver.Hom.op_inj h
    simpa using congr($(hc.uniq (BinaryFan.unop s) m.unop h).op)

end CategoryTheory.Limits

namespace CommRingCat.Under
variable {R : CommRingCat}

/-- A choice of finite products of `(Under R)ᵒᵖ` for `R : CommRingCat` given by the tensor product.
-/
noncomputable instance chosenFiniteProducts : ChosenFiniteProducts (Under R)ᵒᵖ where
  product X Y := {
    cone := BinaryCofan.op <| pushoutCocone.toBinaryCofan.obj <|
      pushoutCocone R (unop X).right (unop Y).right
    isLimit := BinaryCofan.IsColimit.op <| pushoutCocone.IsColimit.toBinaryCofanIsColimit <|
        CommRingCat.pushoutCoconeIsColimit R _ _
  }
  terminal := ⟨_, terminalOpOfInitial Under.mkIdInitial

end CommRingCat.Under

variable {R : CommRingCat} {A : Type*} [CommRing A] [HopfAlgebra R A]


noncomputable instance : Grp_Class <| op <| CommRingCat.mkUnder R A where
  one := op <| (Bialgebra.counitAlgHom R A).toUnder
  mul := op <| by
    change R.mkUnder A  R.mkUnder _
    simp
    /-
    ⊢ R.mkUnder A ⟶ R.mkUnder (TensorProduct ↑R ↑(R.mkUnder A).right ↑(R.mkUnder A).right)
    -/
    --refine (Bialgebra.comulAlgHom R A).toUnder
    sorry
  one_mul' := sorry
  mul_one' := sorry
  mul_assoc' := sorry
  inv := sorry
  left_inv' := sorry
  right_inv' := sorry

Kevin Buzzard (Mar 25 2025 at 18:45):

Thanks. So just to summarise the issue:

If you remove the problematic instance with attribute [-instance] CommRingCat.instAlgebraCarrierRightDiscretePUnit then the first thing that breaks is the instance for ChosenFiniteProducts (Under R)ᵒᵖ, because given X : (Under R)ᵒᵖ Lean needs to find an instance of Algebra ↑R ↑(unop X).right and it can't do so. If you make this instance with docs#CommRingCat.instAlgebraCarrierRightDiscretePUnit then you'll get a diamond if you ever apply it with X = op (R.mkUnder A) for some [Algebra R A] because then ↑(unop X).right is defeq to A but the typeclass inference system finds different (i.e. definitionally different, but propeq) algebra instances on the two types. However if you try to avoid such As and just work with Xs of type (Under R)ᵒᵖ then there is no way to say "I am actually a Hopf algebra" because HopfAlgebra extends Algebra.

In simple terms, if you start with [Algebra R A] and then turn A into a term of type Under R and then back into a type, you end up with a definitionally different algebra instance on a definitionally equal type. This means that it's extremely annoying to do mathematics which relies on both constructions made in type-land (e.g. HopfAlgebra) and in category-land (e.g. ChosenFiniteProducts). A key example of such mathemtics is the theory of group schemes, which is absolutely essential for FLT. So we have a very interesting problem here!

Kevin Buzzard (Mar 25 2025 at 18:50):

Here's the diamond, as noted above, plus the proof that it's propeq:

import Mathlib

variable {R : CommRingCat} {A : Type*} [CommRing A] [Algebra R A]

example : A = (CommRingCat.mkUnder R A) := rfl

def i1 : SMul R A := inferInstance
def i2 : SMul R (CommRingCat.mkUnder R A) := inferInstance

example (r : R) (a : A) : @SMul.smul R A i1 r a = @SMul.smul R A i2 r a := by
  change r  a = (algebraMap (R) A) r * a
  exact Algebra.smul_def r a -- but not `rfl`

Michał Mrugała (Mar 25 2025 at 18:51):

Yeah this summary is pretty much what we've concluded as well. One idea that's been floated is to just define CommAlgCat and work with that instead of Under R. We've managed to deal with the diamonds for proofs of one_mul' and mul_one' but mul_comm' seems extremely painful because this diamond happens internally in the triple tensor product.

Kevin Buzzard (Mar 25 2025 at 18:53):

This discussion needs to move to #mathlib4 so some expert eyes will see it (many of the people who might be able to say something helpful are not subscribed to this channel). I'll start a new thread.

Yaël Dillies (Mar 25 2025 at 19:03):

Can't you move the existing one? EDIT: I guess the point is that you get to write a better summary of the situation

Notification Bot (Mar 25 2025 at 19:06):

This topic was moved here from #new members > Algebra type class inference by Kevin Buzzard.

Eric Wieser (Mar 25 2025 at 19:09):

Fundamentally the issue here is that docs#CommRingCat.instAlgebraCarrierRightDiscretePUnit uses RingHom.toAlgebra, which almost always creates diamonds

Eric Wieser (Mar 25 2025 at 19:09):

But in this case it has no other choice, because the SMul instance which is carried by Algebra to avoid the diamond cannot be carried by CategoryTheory.Under R

Kevin Buzzard (Mar 25 2025 at 19:09):

I wonder whether a way of fixing the issue is defining CommAlgCat R so that the objects are (edit: types A equipped with) terms of type Algebra R A

Eric Wieser (Mar 25 2025 at 19:10):

Yes, I think this is an argument for not defining CommAlgCat in terms of Under

Eric Wieser (Mar 25 2025 at 19:11):

@Kyle Miller, do you have any idea where DiscretePUnit is being inserted in the name from? nevermind, it's from expanding Under

Kevin Buzzard (Mar 25 2025 at 19:12):

Is there another highly disruptive but possible approach, involving redefining Algebra R A as a ring morphism and defining the SMul to be f(r) * a? Or is this impossible for other reasons?

Eric Wieser (Mar 25 2025 at 19:13):

That's impossible for other reasons, consider A := Matrix n n R and the natural module structure on matrices: diagonal (algebraMap _ _ r) * M is not possible to make defeq to r • M

Eric Wieser (Mar 25 2025 at 19:15):

Maybe CategoryTheory.Under could take some extra [UnderData R] assumption, which for CommRingCat carries the smul action?

Michał Mrugała (Mar 25 2025 at 20:11):

CommAlgCat seems to be working well

Kim Morrison (Mar 25 2025 at 21:37):

Can someone remind me why we wanted to avoid a hand-rolled CommAlgCat in favour of using Under? Just avoiding having two ways to say the same thing?

Andrew Yang (Apr 03 2025 at 16:00):

Yes. And to apply the general category theoretic machinery about Over categories.


Last updated: May 02 2025 at 03:31 UTC