Zulip Chat Archive

Stream: general

Topic: the [grind] attribute cannot be applied at all


Asei Inoue (Jul 15 2025 at 12:04):

I found an example where the [grind] attribute cannot be applied at all, but I don’t understand why.
I’d like to know the reason.

variable {A B C : Type}

theorem comp_eq {f : A  B} {g : B  C} {h : A  C} (heq : g  f = h) (a : A) : g (f a) = h a := calc
  _ = (g  f) a := rfl
  _ = h a := by rw [heq]

-- For some reason, the `[grind]` attribute cannot be applied at all
/--
error: `@[grind] theorem comp_eq` failed to find patterns, consider using different options or the `grind_pattern` command
-/
#guard_msgs in
attribute [grind] comp_eq

/--
error: `@[grind =>] theorem comp_eq` failed to find patterns searching from left to right, consider using different options or the `grind_pattern` command
-/
#guard_msgs in
attribute [grind =>] comp_eq

/--
error: invalid pattern, (non-forbidden) application expected
  @#3 (@#4 #0)
-/
#guard_msgs in
attribute [grind =] comp_eq

Floris van Doorn (Jul 15 2025 at 12:26):

Did you try the grind_pattern command? See reference manual: https://lean-lang.org/doc/reference/latest//The--grind--tactic/E___matching/#The-Lean-Language-Reference--The--grind--tactic--E___matching

Asei Inoue (Jul 15 2025 at 12:35):

Did you try the grind_pattern command? See reference manual: https://lean-lang.org/doc/reference/latest//The--grind--tactic/E___matching/#The-Lean-Language-Reference--The--grind--tactic--E___matching

I don't know how to use grind_pattern...

Jovan Gerbscheid (Jul 15 2025 at 14:33):

I don't think this is a reasonable grind lemma. Do you want it to apply if g ∘ f = h is in the context? in that case there is no way to find a.

Asei Inoue (Jul 20 2025 at 06:26):

Originally, I was trying to golf the following proof using grind.
If there's a good way to do it, I'd love to know.

namespace Function

variable {A B : Type}

/-- Injectivity of a function -/
def Injective (f : A  B) : Prop :=
   (x y : A), f x = f y  x = y

/-- Surjectivity of a function -/
def Surjective (f : A  B) : Prop :=
   y : B,  x : A, f x = y

variable {C : Type}
variable {f : B  C} {g : A  B}

/-- If the composition is surjective, then so is the outer function. -/
theorem surj_of_comp_surj (h : Surjective (f  g)) : Surjective f := by
  dsimp [Surjective] at *
  -- Actually, this can be solved with `try?`
  intro c
  have a, ha := h c
  grind

/-- If the composition is injective, then the inner function is injective. -/
theorem inj_of_comp_inj (h : Injective (f  g)) : Injective g := by
  dsimp [Injective] at *
  -- Actually, this can be solved with `try?`
  intro a₁ a₂ g_eq
  replace h := h a₁ a₂
  grind

/-- Monomorphism -/
def mono (f : A  B) : Prop :=
   C : Type,  g₁ g₂ : C  A, f  g₁ = f  g₂  g₁ = g₂

/-- An injective function is a monomorphism -/
theorem mono_of_inj {f : A  B} (h : Injective f) : mono f := by
  intro C g₁ g₂ g_eq
  dsimp [Injective] at h
  ext c
  fail_if_success grind -- **TODO** How can we prove this using `grind`?
  have eq : f (g₁ c) = f (g₂ c) := calc
    _ = (f  g₁) c := rfl
    _ = (f  g₂) c := by rw [g_eq]
    _ = f (g₂ c) := rfl
  replace h := h (g₁ c) (g₂ c) eq
  assumption

/-- A monomorphism is injective -/
theorem inj_of_mono {f : A  B} (h : mono f) : Injective f := by
  intro a₁ a₂ f_eq
  dsimp [mono] at h

  let C := Fin 2
  let g₁ : C  A := fun _ => a₁
  let g₂ : C  A := fun _ => a₂
  replace h := h C g₁ g₂

  fail_if_success grind -- **TODO** How can we prove this using `grind`?
  have : f  g₁ = f  g₂ := by grind
  replace h := h this

  have : a₁ = a₂ := calc
    _ = g₁ 0 := rfl
    _ = g₂ 0 := by rw [h]
    _ = a₂ := rfl
  assumption

/-- Epimorphism -/
def epi (f : A  B) :=  C : Type,  g₁ g₂ : B  C, g₁  f = g₂  f  g₁ = g₂

/-- A surjective function is an epimorphism -/
theorem epi_of_surj {f : A  B} (h : Surjective f) : epi f := by
  intro C g₁ g₂ g_eq
  dsimp [Surjective] at h
  ext b
  obtain a, ha := h b
  rw [ ha]

  -- Why does `grind` not succeed here?
  fail_if_success grind

  have : g₁ (f a) = g₂ (f a) := calc
    _ = (g₁  f) a := rfl
    _ = (g₂  f) a := by rw [g_eq]
    _ = g₂ (f a) := rfl
  assumption

end Function

Kim Morrison (Jul 23 2025 at 03:40):

Change your definitions of mono and epi so they are about fully applied functions. grind will be happier.

Asei Inoue (Jul 23 2025 at 11:47):

@Kim Morrison

they are about fully applied functions

what is "fully applied functions"? How should I change the definitions?

Patrick Massot (Jul 23 2025 at 11:51):

If f has type α → β → γ then f a b is fully applied while f a is only partially applied.

Asei Inoue (Jul 23 2025 at 11:54):

:(

/-- モノ射 -/
def mono (f : A  B) : Prop :=
   C : Type,  g₁ g₂ : C  A, f  g₁ = f  g₂  g₁ = g₂

/- `@[grind] theorem Function.mono_grind` failed to find patterns, consider using different options or the `grind_pattern` command -/
@[grind]
theorem mono_grind (f : A  B) (h : mono f) {C : Type} {g₁ g₂ : C  A} (hcomp :  c, (f  g₁) c = (f  g₂) c) :
   c, g₁ c = g₂ c := by
  intro c
  have eq : f  g₁ = f  g₂ := by grind
  have g_eq : g₁ = g₂ := h C g₁ g₂ eq
  grind

Jovan Gerbscheid (Jul 23 2025 at 12:41):

I think what @Kim Morrison means is to make epi and mono into a one field structure, or to use irreducible_def.

I was also wondering: in the grind manual, it says that grind has special support for the injectivity of inductive constructors. But as far as I could tell, grind does not support any other kinds of injectivity lemmas. Is that right?


Last updated: Dec 20 2025 at 21:32 UTC