Zulip Chat Archive

Stream: mathlib4

Topic: Instance diamond in algebra hierarchy?


Michael Stoll (Jan 13 2025 at 15:52):

Consider:

import Mathlib.Algebra.Ring.Equiv

/-- A type synonym. -/
def Foo (R : Type*) := R

namespace Foo

variable {R : Type*} [Semiring R]
/- remove `[Semiring R]` --> error goes away -/

instance instSemiring [Semiring R] : Semiring (Foo R) := inferInstanceAs (Semiring R)

instance instRing [Ring R] : Ring (Foo R) := inferInstanceAs (Ring R)

example [Ring R] : True := by
  let i : NonUnitalNonAssocSemiring (Foo R) := NonUnitalNonAssocRing.toNonUnitalNonAssocSemiring
  let i' : NonUnitalNonAssocSemiring (Foo R) :=  NonAssocSemiring.toNonUnitalNonAssocSemiring
  have : i = i' := rfl -- error
  sorry

variable (R) in
/-- Canonical (semi)ring equivalence between `Foo R` and `R`. -/
def equiv [Semiring R] : Foo R ≃+* R := RingEquiv.refl _

variable [Ring R]

/- equiv x : Foo R ≃+* R -/
#check Foo.equiv R

/-
synthesized type class instance is not definitionally equal to expression inferred by typing rules, synthesized
  @Distrib.toMul (Foo R)
    (@NonUnitalNonAssocSemiring.toDistrib (Foo R) NonUnitalNonAssocRing.toNonUnitalNonAssocSemiring)
inferred
  @Distrib.toMul (Foo R) (@NonUnitalNonAssocSemiring.toDistrib (Foo R) NonAssocSemiring.toNonUnitalNonAssocSemiring)
-/
#check (Foo.equiv R).symm

What is going on here? How can the spurious [Semiring R] variable that none of the declarations actually use lead to non-defeq instances in the example? And why is the problem triggered by applying RingEquiv.symm and not already on Foo.equiv R?

Eric Wieser (Jan 13 2025 at 15:56):

/- remove `[Semiring R]` --> error goes away -/

Yes, because your example is example [Semiring R] [Ring R]

Michael Stoll (Jan 13 2025 at 15:57):

Hovering says Foo._example.{u_1} {R : Type u_1} [Ring R] : True, so no [Semiring R]?

Eric Wieser (Jan 13 2025 at 15:58):

Not if you comment out the line that fails

Eric Wieser (Jan 13 2025 at 15:58):

Or change it to have : i = i' := by exact rfl

Eric Wieser (Jan 13 2025 at 15:59):

If you try:

def foo [Ring R] : True := by
  let i : NonUnitalNonAssocSemiring (Foo R) := NonUnitalNonAssocRing.toNonUnitalNonAssocSemiring
  let i' : NonUnitalNonAssocSemiring (Foo R) :=  NonAssocSemiring.toNonUnitalNonAssocSemiring
  have : i = i' := rfl -- error
  sorry

#print foo

then you'll see that the error somehow truncates the term after the first let

Eric Wieser (Jan 13 2025 at 15:59):

(remember that example means def)

Michael Stoll (Jan 13 2025 at 16:06):

OK, thanks. I came across this in file#Mathlib/Analysis/Normed/Ring/WithAbs :

variable {R S K : Type*} [Semiring R] [OrderedSemiring S] [Field K]

/-- Type synonym for a semiring which depends on an absolute value. This is a function that takes
an absolute value on a semiring and returns the semiring. We use this to assign and infer instances
on a semiring that depend on absolute values. -/
@[nolint unusedArguments]
def WithAbs : AbsoluteValue R S  Type _ := fun _ => R

namespace WithAbs

variable (v : AbsoluteValue R )

/-- Canonical equivalence between `WithAbs v` and `R`. -/
def equiv : WithAbs v  R := Equiv.refl (WithAbs v)

-- (...)

instance instSemiring : Semiring (WithAbs v) := inferInstanceAs (Semiring R)

instance instRing [Ring R] : Ring (WithAbs v) := inferInstanceAs (Ring R)

-- (...)

instance normedRing {R : Type*} [Ring R] (v : AbsoluteValue R ) : NormedRing (WithAbs v) :=
  v.toNormedRing

and I got the error (on (WithAbs.equiv v).symm) after changing equiv to be a semiring isomorphism.

I bet this is not the only place in Mathlib where this problematic setup shows up...

Sébastien Gouëzel (Jan 13 2025 at 16:32):

This can only fail in sections which don't have lemmas or theorems (as for these the unused linter would fire), so it shouldn't happen often.

Michael Stoll (Jan 13 2025 at 16:33):

I think the problem is that the declaration indeed uses both arguments, which leads to the failure. (I did not get any linter warnings.)


Last updated: May 02 2025 at 03:31 UTC