Zulip Chat Archive

Stream: general

Topic: how to make `grind` tactic aware of type class instances?


Syed Shaazib Tanvir (Jan 09 2026 at 14:55):

I have the following code

class SetTheory where
  Set : Type u
  Object : Type v
  mem : Object  Set  Prop
  extensionality (x : Set) (y : Set) : ( z : Object, mem z x  mem z y)  x = y
  empty : Set
  empty_set_axiom :  x : Object, ¬mem x empty
  singleton (x : Object) : Set
  singleton_axiom (x : Object) :  y : Object, mem y (singleton x)  y = x
  pair_axiom (x : Object) (y : Object) :  z : Set,  w : Object, mem w z  (w = x  w = y)
  pairwise_union (x : Set) (y : Set) : Set
  pairwise_union_axiom (x : Set) (y : Set) (z : Object)
    : mem z (pairwise_union x y)  (mem z x  mem z y)

export SetTheory (Set Object)
variable [SetTheory]

@[grind]
instance SetTheory.instMembership : Membership Object Set where
  mem x y := mem y x

@[grind]
instance SetTheory.instUnion : Union Set where
  union x y := pairwise_union x y

theorem SetTheory.union_comm (x y : Set) : x  y = y  x := by
  change pairwise_union x y = pairwise_union y x
  apply extensionality
  intro z
  constructor
  · grind only [pairwise_union_axiom]
  · grind only [pairwise_union_axiom]

Removing the change pairwise_union x y = pairwise_union y x causes the grind tactic to fail even though the relevant type class instances have the @[grind] attribute. How can I fix this?

Miyahara Kō (Jan 09 2026 at 18:59):

Generally speaking, grind attributes for instances essentially do nothing.
You should remove grind attributes from instances and make new grind lemmas, and change grind only into grind.

Marcus Rossel (Jan 17 2026 at 11:05):

@Miyahara Kō what kind of grind lemmas should be implemented? I've had similar situations where I was expecting grind to just understand what a given notation (implemented on type classes) unfolds to, and ended up adding explicit lemmas just for unfolding the notation. But that felt a bit strange as other tactics like simp don't require such lemmas.

Théophile (Jan 17 2026 at 14:27):

This issue I opened the last month is probably relevant: lean4#11708

The corresponding MWE is:

class Test (α: Type) where
  pred: α  Prop

instance: Test Unit where
  pred _ := True

example: Test.pred () := by
  fail_if_success grind [Test.pred]
  grind [Test.pred, instTestUnit]

Miyahara Kō (Jan 17 2026 at 22:14):

@Marcus Rossel

class SetTheory where
  Set : Type u
  Object : Type v
  mem : Object  Set  Prop
  extensionality (x : Set) (y : Set) : ( z : Object, mem z x  mem z y)  x = y
  empty : Set
  empty_set_axiom :  x : Object, ¬mem x empty
  singleton (x : Object) : Set
  singleton_axiom (x : Object) :  y : Object, mem y (singleton x)  y = x
  pair_axiom (x : Object) (y : Object) :  z : Set,  w : Object, mem w z  (w = x  w = y)
  pairwise_union (x : Set) (y : Set) : Set
  pairwise_union_axiom (x : Set) (y : Set) (z : Object)
    : mem z (pairwise_union x y)  (mem z x  mem z y)

export SetTheory (Set Object)
variable [SetTheory]

instance SetTheory.instMembership : Membership Object Set where
  mem x y := mem y x

@[grind =]
theorem SetTheory.mem_def {x : Object} {y : Set} : x  y  SetTheory.mem x y :=
  Iff.rfl

instance SetTheory.instUnion : Union Set where
  union x y := pairwise_union x y

@[grind =]
theorem SetTheory.union_def (x y : Set) : x  y = pairwise_union x y :=
  rfl

theorem SetTheory.union_comm (x y : Set) : x  y = y  x := by
  apply extensionality
  intro z
  constructor
  · grind [pairwise_union_axiom]
  · grind [pairwise_union_axiom]

Miyahara Kō (Jan 17 2026 at 22:53):

My refactored version


Last updated: Feb 28 2026 at 14:05 UTC