Previously, the tactic state shown at `decreasing_by` would leak lots of details about the translation, and mention `invImage`, `PSigma` etc. This is not nice. So this introduces `clean_wf`, which is like `simp_wf` but using `simp`'s `only` mode, and runs this unconditionally. This should clean up the goal to a reasonable extent. Previously `simp_wf` was an unrestricted `simp […]` call, but we probably don’t want arbitrary simplification to happen at this point, so this now became `simp only` call. For backwards compatibility, `decreasing_with` begins with `try simp`. The `simp_wf` tactic is still available to not break too much existing code; it’s docstring suggests to no longer use it. With `set_option cleanDecreasingByGoal false` one can disable the use of `clean_wf`. I hope this is only needed for debugging and understanding. Migration advise: If your `decreasing_by` proof begins with `simp_wf`, either remove that (if the proof still goes through), or replace with `simp`. I am a bit anxious about running even `simp only` unconditionally here, as it may do more than some user might want, e.g. because of options like `zetaDelta := true`. We'll see if we need to reign in this tactic some more. I wonder if in corner cases the `simp_wf` tactic might be able to close the goal, and if that is a problem. If so, we may have to promote simp’s internal `mayCloseGoal` parameter to a simp configuration option and use that here. fixes #4928
70 lines
1.6 KiB
Text
70 lines
1.6 KiB
Text
mutual
|
||
def f : Nat → α → α → α
|
||
| 0, a, b => a
|
||
| n, a, b => g a n b |>.1
|
||
termination_by n _ _ => (n, 2)
|
||
decreasing_by
|
||
apply Prod.Lex.right
|
||
decide
|
||
|
||
def g : α → Nat → α → (α × α)
|
||
| a, 0, b => (a, b)
|
||
| a, n, b => (h a b n, a)
|
||
termination_by _ n _ => (n, 1)
|
||
decreasing_by
|
||
apply Prod.Lex.right
|
||
decide
|
||
|
||
def h : α → α → Nat → α
|
||
| a, b, 0 => b
|
||
| a, b, n+1 => f n a b
|
||
termination_by _ _ n => (n, 0)
|
||
decreasing_by
|
||
apply Prod.Lex.left
|
||
apply Nat.lt_succ_self
|
||
end
|
||
|
||
/-- info: 'a' -/
|
||
#guard_msgs in
|
||
#eval f 5 'a' 'b'
|
||
|
||
/-- info: @f.eq_1 : ∀ {α : Type u_1} (x x_1 : α), f 0 x x_1 = x -/
|
||
#guard_msgs in
|
||
#check @f.eq_1
|
||
/--
|
||
info: @f.eq_2 : ∀ {α : Type u_1} (x : Nat) (x_1 x_2 : α), (x = 0 → False) → f x x_1 x_2 = (g x_1 x x_2).fst
|
||
-/
|
||
#guard_msgs in
|
||
#check @f.eq_2
|
||
/--
|
||
info: @f.eq_def : ∀ {α : Type u_1} (x : Nat) (x_1 x_2 : α),
|
||
f x x_1 x_2 =
|
||
match x, x_1, x_2 with
|
||
| 0, a, b => a
|
||
| n, a, b => (g a n b).fst
|
||
-/
|
||
#guard_msgs in
|
||
#check @f.eq_def
|
||
/-- error: unknown identifier 'f.eq_3' -/
|
||
#guard_msgs in
|
||
#check @f.eq_3
|
||
|
||
/-- info: @h.eq_1 : ∀ {α : Type u_1} (x x_1 : α), h x x_1 0 = x_1 -/
|
||
#guard_msgs in
|
||
#check @h.eq_1
|
||
/-- info: @h.eq_2 : ∀ {α : Type u_1} (x x_1 : α) (n : Nat), h x x_1 n.succ = f n x x_1 -/
|
||
#guard_msgs in
|
||
#check @h.eq_2
|
||
/--
|
||
info: @h.eq_def : ∀ {α : Type u_1} (x x_1 : α) (x_2 : Nat),
|
||
h x x_1 x_2 =
|
||
match x, x_1, x_2 with
|
||
| a, b, 0 => b
|
||
| a, b, n.succ => f n a b
|
||
-/
|
||
#guard_msgs in
|
||
#check @h.eq_def
|
||
|
||
/-- error: unknown identifier 'h.eq_3' -/
|
||
#guard_msgs in
|
||
#check @h.eq_3
|