Zulip Chat Archive

Stream: general

Topic: beefing up `convert`


Kevin Buzzard (Jan 22 2022 at 18:35):

I might have asked this before but I can't find the thread; perhaps someone already told me why this can't happen. I can imagine a beefed-up convert which makes much more progress on the goals below.

import tactic
import data.real.basic

-- proof that aₙ → t implies -aₙ → -t
example {a :   } {t : }
  (ha :  (ε : ), 0 < ε  ( (B : ),  (n : ), B  n  |a n - t| < ε)) :
         (ε : ), 0 < ε  ( (B : ),  (n : ), B  n  | -a n - -t| < ε) :=
begin
  convert ha, -- using 4 or whatever
  -- want: ∀ n, |a n - t| = | -a n - -t|
  -- but get
  -- ⊢ ∀ ε, ... = ∀ ε, ...
  sorry,
  --
end

-- workaround
example {a :   } {t : }
  (ha :  (ε : ), 0 < ε  ( (B : ),  (n : ), B  n  |a n - t| < ε)) :
         (ε : ), 0 < ε  ( (B : ),  (n : ), B  n  | -a n - -t| < ε) :=
begin
  -- I want this to be the goal so I don't have to type it
  have :  n : , |a n - t| = | -a n - -t|,
  { intro n,
    rw abs_sub_comm,
    congr' 1,
    ring },
  simpa [this] using ha,
end

-- minimised convert "failure"
example (P Q R : Prop) (h : P  Q) : P  R :=
begin
  convert h,
  -- ⊢ (P → R) = (P → Q)
  -- Why not `R = Q` or `R ↔ Q`?
  sorry,
end

example (f :   ) (a b : ) (h :  n, f n = a) :  n, f n = b :=
begin
  convert h, -- expecting `b = a`
  -- ⊢ (∀ (n : ℕ), f n = b) = ∀ (n : ℕ), f n = a
  sorry
end

Reid Barton (Jan 22 2022 at 18:46):

So the first-order explanation is that congr checks for a function application, and a Pi/forall/function type (P → R) is not a function application

Reid Barton (Jan 22 2022 at 18:47):

But, I don't see why congr couldn't also try applying a suitable version of docs#forall_congr (followed by intro) and then continuing

Kyle Miller (Jan 22 2022 at 18:51):

This reminds me of a tactic I wrote as an exercise that does sort of what you want here. https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there.20code.20for.20X.3F/topic/Automatic.20intro.2Fcases.2Fspecialize.2Fuse.20dance/near/203997071

Kyle Miller (Jan 22 2022 at 18:51):

example {a :   } {t : }
  (ha :  (ε : ), 0 < ε  ( (B : ),  (n : ), B  n  |a n - t| < ε)) :
         (ε : ), 0 < ε  ( (B : ),  (n : ), B  n  | -a n - -t| < ε) :=
begin
  enter ha with ε εpos B n hB,
  /-
a : ℕ → ℝ,
t ε : ℝ,
εpos : 0 < ε,
B n : ℕ,
hB : B ≤ n,
ha : |a n - t| < ε
⊢ | -a n - -t| < ε
  -/
  sorry
end

example (P Q R : Prop) (h : P  Q) : P  R :=
begin
  enter h with hP,
  /-
P Q R : Prop,
hP : P,
h : Q
⊢ R
  -/
  sorry,
end

example (f :   ) (a b : ) (h :  n, f n = a) :  n, f n = b :=
begin
  enter h with n,
  /-
f : ℕ → ℝ,
a b : ℝ,
n : ℕ,
h : f n = a
⊢ f n = b
  -/
  sorry
end

Kyle Miller (Jan 22 2022 at 18:51):

Code

Kyle Miller (Jan 22 2022 at 19:01):

Reid Barton said:

But, I don't see why congr couldn't also try applying a suitable version of docs#forall_congr (followed by intro) and then continuing

Maybe convert/congr could get a with clause so you can name those variables being introduced?

Eric Wieser (Jan 22 2022 at 21:41):

congr' already has such a clause


Last updated: Dec 20 2023 at 11:08 UTC