Replaces `@[eliminator]` with two attributes `@[induction_eliminator]` and `@[cases_eliminator]` for defining custom eliminators for the `induction` and `cases` tactics, respectively. Adds `Nat.recAux` and `Nat.casesAuxOn`, which are eliminators that are defeq to `Nat.rec` and `Nat.casesOn`, but these use `0` and `n + 1` rather than `Nat.zero` and `Nat.succ n`. For example, using `induction` to prove that the factorial function is positive now has the following goal states (thanks also to #3616 for the goal state after unfolding). ```lean example : 0 < fact x := by induction x with | zero => decide | succ x ih => /- x : Nat ih : 0 < fact x ⊢ 0 < fact (x + 1) -/ unfold fact /- ... ⊢ 0 < (x + 1) * fact x -/ simpa using ih ``` Thanks to @adamtopaz for initial work on splitting the `@[eliminator]` attribute.
31 lines
1,018 B
Text
31 lines
1,018 B
Text
@[induction_eliminator] protected def Nat.recDiag {motive : Nat → Nat → Sort u}
|
|
(zero_zero : motive 0 0)
|
|
(succ_zero : (x : Nat) → motive x 0 → motive (x + 1) 0)
|
|
(zero_succ : (y : Nat) → motive 0 y → motive 0 (y + 1))
|
|
(succ_succ : (x y : Nat) → motive x y → motive (x + 1) (y + 1))
|
|
(x y : Nat) : motive x y :=
|
|
let rec go : (x y : Nat) → motive x y
|
|
| 0, 0 => zero_zero
|
|
| x+1, 0 => succ_zero x (go x 0)
|
|
| 0, y+1 => zero_succ y (go 0 y)
|
|
| x+1, y+1 => succ_succ x y (go x y)
|
|
termination_by x y => (x, y)
|
|
go x y
|
|
|
|
def f (x y : Nat) :=
|
|
match x, y with
|
|
| 0, 0 => 1
|
|
| x+1, 0 => f x 0
|
|
| 0, y+1 => f 0 y
|
|
| x+1, y+1 => f x y
|
|
termination_by (x, y)
|
|
|
|
example (x y : Nat) : f x y > 0 := by
|
|
induction x, y with
|
|
| zero_zero => decide
|
|
| succ_zero x ih => simp [f, ih]
|
|
| zero_succ y ih => simp [f, ih]
|
|
| succ_succ x y ih => simp [f, ih]
|
|
|
|
example (x y : Nat) : f x y > 0 := by
|
|
induction x, y <;> simp (config := { decide := true }) [f, *]
|