Zulip Chat Archive

Stream: new members

Topic: apply? suggested something that led to an error


Kevin Cheung (Mar 28 2024 at 13:29):

I tried the following:

import Mathlib.Algebra.BigOperators.Fin
import Mathlib.Data.Real.Sqrt

example (n : ) (a: Fin (n + 1)  Fin (Nat.zero + 1)) :  i : Fin (n + 1), a i = 0 := by
  apply?

Lean said:

Try this: exact fun i  eq_zero_of_zero_eq_one rfl (a i)

But the following gives an error on rfl.

import Mathlib.Algebra.BigOperators.Fin
import Mathlib.Data.Real.Sqrt

example (n : ) (a: Fin (n + 1)  Fin (Nat.zero + 1)) :  i : Fin (n + 1), a i = 0 := by
  exact fun i  eq_zero_of_zero_eq_one rfl (a i)

From the InfoView:

FinError.lean:5:39
application type mismatch
  eq_zero_of_zero_eq_one rfl
argument
  rfl
has type
  0 = 0 : Prop
but is expected to have type
  0 = 1 : Prop

I have two questions:

  1. Should we expect apply? to suggest something that Lean might not accept?
  2. Is the example provable?

Kyle Miller (Mar 28 2024 at 13:39):

If apply? responds with something, it is provable.

And yes, we do expect apply? to suggest things that Lean might not accept — but, it's not that there's no proof, it's that it didn't pretty print the proof it derived in a way that can be read back in and interpreted correctly. (We expect it only because of limitations in the pretty printer's ability to succeed in "round tripping".)

Kyle Miller (Mar 28 2024 at 13:41):

Sometimes setting set_option pp.analysis true gets it to pretty print with enough information to work. That doesn't appear to work here however.

Kyle Miller (Mar 28 2024 at 13:42):

set_option pp.explicit true works

Kyle Miller (Mar 28 2024 at 13:42):

example (n : ) (a: Fin (n + 1)  Fin (Nat.zero + 1)) :  i : Fin (n + 1), a i = 0 := by
  exact fun i 
    @eq_zero_of_zero_eq_one (Fin (@HAdd.hAdd Nat Nat Nat (@instHAdd Nat instAddNat) Nat.zero 1))
      (@NonAssocSemiring.toMulZeroOneClass
        (Fin (@HAdd.hAdd Nat Nat Nat (@instHAdd Nat instAddNat) Nat.zero 1))
        (@Semiring.toNonAssocSemiring
          (Fin (@HAdd.hAdd Nat Nat Nat (@instHAdd Nat instAddNat) Nat.zero 1))
          (@CommSemiring.toSemiring
            (Fin (@HAdd.hAdd Nat Nat Nat (@instHAdd Nat instAddNat) Nat.zero 1))
            (@CommRing.toCommSemiring
              (Fin (@HAdd.hAdd Nat Nat Nat (@instHAdd Nat instAddNat) Nat.zero 1))
              (@Fin.instCommRing (@HAdd.hAdd Nat Nat Nat (@instHAdd Nat instAddNat) Nat.zero 1)
                (@NeZero.succ Nat.zero))))))
      (@rfl (Fin (@HAdd.hAdd Nat Nat Nat (@instHAdd Nat instAddNat) Nat.zero 1)) 0) (a i)

Kyle Miller (Mar 28 2024 at 13:42):

Once you have that, you can simplify the term by hand.

Kyle Miller (Mar 28 2024 at 13:44):

example (n : ) (a: Fin (n + 1)  Fin (Nat.zero + 1)) :  i : Fin (n + 1), a i = 0 := by
  exact fun i  eq_zero_of_zero_eq_one (Eq.refl (0 : Fin 1)) (a i)

Kevin Cheung (Mar 28 2024 at 13:50):

Thanks for the proof. Could the limitation be overcome?

Kyle Miller (Mar 28 2024 at 13:52):

Well, set_option pp.all true theoretically overcomes that limitation, at the cost of having unreadable terms :-)

Kyle Miller (Mar 28 2024 at 13:54):

The set_option pp.analyze true option was meant to try to make round tripping work, but (1) as we see in this example, it doesn't always work and (2) apparently in practice it was too verbose as a default for all pretty printing.

Kyle Miller (Mar 28 2024 at 13:55):

exact? and apply? should probably pretty print with pp.analyze true (and that algorithm needs more attention)

Kevin Cheung (Mar 28 2024 at 13:56):

Thanks for the explanation.

Damiano Testa (Mar 28 2024 at 16:08):

Sometimes I think that apply? also mistakes which variables to use where.

Damiano Testa (Mar 28 2024 at 16:10):

See for instance this example, where, besides the incorrect Ne.symm and metavariables, the second variable should have been H instead of repeated hc.

Michael Stoll (Apr 12 2024 at 15:51):

Here is another problem:

import Mathlib

lemma main_odd {a : } (ha' : Odd a) :
    0  4 + a := by
  intro heq
  have ha'' : Odd (4 + a) := by
    -- `apply?` suggests
    refine Nat.odd_add'.mpr (?_ (id heq.symm))
    -- which gives an error on `(?_ (id heq.symm))`
  sorry

Why is apply? producing suggestions involving expressions like (?_ (id heq.symm)) above? It does not seem to make a lot of sense.

Kyle Miller (Apr 12 2024 at 16:05):

That's weird. The goals that apply? reports show that it's really just saying "you can prove this by reverting heq"

Try this: refine Nat.odd_add'.mpr (?_ (id heq.symm))
Remaining subgoals:
⊢ 4 + a = 0 → (Odd a ↔ Even 4)
⊢ Odd a ↔ Even 4

Michael Stoll (Apr 12 2024 at 16:41):

But the second subgoal subsumes the first, so reverting heq is completely unnecessary.

Michael Stoll (Apr 12 2024 at 19:00):

Here is another failure:

import Mathlib.Data.Int.Basic

example (a b c : ) (ha : a  0) (h : a * b = a * c) : b = c := by
  -- exact? fails, apply? does not produce anything useful
  exact Int.eq_of_mul_eq_mul_left ha h

It works when I remove the import.

Michael Stoll (Apr 12 2024 at 19:03):

The first suggestion from apply? is

Try this: refine Int.neg_inj.mp (?_ (id (Ne.symm ha)))
Remaining subgoals:
 0  a  -b = -c
 a * c = a * b  -b = -c
 -b = -c

where again the last subgoal implies the other two (and this occurs a lot). It should just produce

Try this: refine Int.neg_inj.mp ?_
Remaining subgoals:
 -b = -c

(not that this is useful in the example...).

Michael Stoll (Apr 12 2024 at 19:54):

@Kim Morrison :up:

Michael Stoll (Apr 13 2024 at 10:29):

You really don't want the first suggestion apply? produces to look like that:

Try this: refine help (?_ (id heq.symm)) (?_ (id heq.symm)) (?_ (id heq.symm))
Remaining subgoals:
 8 * b * (1 + 2 * b ^ 3) = X ^ 2 - 7 * (2 * b) * Y ^ 2  
 8 * b * (1 + 2 * b ^ 3) = X ^ 2 - 7 * (2 * b) * Y ^ 2  
 8 * b * (1 + 2 * b ^ 3) = X ^ 2 - 7 * (2 * b) * Y ^ 2  
 8 * b * (1 + 2 * b ^ 3) = X ^ 2 - 7 * (2 * b) * Y ^ 2  
 8 * b * (1 + 2 * b ^ 3) = X ^ 2 - 7 * (2 * b) * Y ^ 2  
 8 * b * (1 + 2 * b ^ 3) = X ^ 2 - 7 * (2 * b) * Y ^ 2  IsCoprime (?m.63791 ) (?m.60679 )
 8 * b * (1 + 2 * b ^ 3) = X ^ 2 - 7 * (2 * b) * Y ^ 2 
  ?m.70015  ^ 2 - ?m.66903  * ?m.73127  ^ 2 = ?m.63791  * (?m.60679 )
 8 * b * (1 + 2 * b ^ 3) = X ^ 2 - 7 * (2 * b) * Y ^ 2  J(?m.66903  | ?m.60679 ) = -1
 -1 = J(7 * (2 * b) | 1 + 2 * b ^ 3)  
 
 -1 = J(7 * (2 * b) | 1 + 2 * b ^ 3)  
 
 -1 = J(7 * (2 * b) | 1 + 2 * b ^ 3)  
 
 -1 = J(7 * (2 * b) | 1 + 2 * b ^ 3)  
 
 -1 = J(7 * (2 * b) | 1 + 2 * b ^ 3)  
 
 -1 = J(7 * (2 * b) | 1 + 2 * b ^ 3)  IsCoprime (?m.63791 ) (?m.60679 )
 IsCoprime (?m.63791 ) (?m.60679 )
 -1 = J(7 * (2 * b) | 1 + 2 * b ^ 3)  ?m.70015  ^ 2 - ?m.66903  * ?m.73127  ^ 2 = ?m.63791  * (?m.60679 )
 ?m.70015  ^ 2 - ?m.66903  * ?m.73127  ^ 2 = ?m.63791  * (?m.60679 )
 -1 = J(7 * (2 * b) | 1 + 2 * b ^ 3)  J(?m.66903  | ?m.60679 ) = -1
 J(?m.66903  | ?m.60679 ) = -1

Am I the only one who is seeing this?

Michael Stoll (Apr 13 2024 at 10:55):

This seems to be a fairly recent regression.

Michael Stoll (Apr 13 2024 at 20:23):

I think I have found the declaration that changes the behavior of apply? from "good" to "bad" (but I have no idea how it does it):

axiom f : Nat  Nat

theorem test (m n : Nat) (h : n = f m) : f n = f m := sorry

attribute [symm] Eq.symm -- set in `Mathlib.Init.Logic`

theorem foo (a : Nat) (h : a = 6) : f a = f 3 := by
  apply?
  /-
  Try this: refine test 3 a (?_ (id h.symm))
  Remaining subgoals:
  ⊢ 6 = a → a = f 3
  ⊢ a = f 3 -/

-- without `attribute [symm] Eq.symm`:
  /-
  Try this: refine test 3 a ?h
  Remaining subgoals:
  ⊢ a = f 3
  -/

file#Mathlib/Init/Logic in line 45 does

attribute [symm] Eq.symm

Whatever the intended effect is, it also has the unintended effect on apply? shown above.
A knock-on effect of this bad behavior seems to be that the text produced by apply? in the infoview is extremely bloated, which (at least on my fairly fast laptop) makes scrolling through it in VSCode extremely sluggish, so that apply? becomes almost unusable except in very simple situations. (This had been much better until fairly recently.)

Michael Stoll (Apr 13 2024 at 20:52):

The symm attribute is defined in Lean/Meta/Tactic/Symm.lean, which seems to have been created by lean4#3408 (maybe moved from Std). @Joe Hendrix
The problematic behavior of apply? seems to predate the merging of this PR, though...

Michael Stoll (Apr 14 2024 at 09:48):

Moving the discussion here.


Last updated: May 02 2025 at 03:31 UTC