This PR implements a new E-matching pattern inference procedure that is faithful to the behavior documented in the reference manual regarding minimal indexable subexpressions. The old inference procedure was failing to enforce this condition. For example, the manual documents `[grind ->]` as follows `[@grind →]` selects a multi-pattern from the hypotheses of the theorem. In other words, `grind` will use the theorem for forwards reasoning. To generate a pattern, it traverses the hypotheses of the theorem from left to right. Each time it encounters a **minimal indexable subexpression** which covers an argument which was not previously covered, it adds that subexpression as a pattern, until all arguments have been covered. That said, the new procedure is currently disabled, and the following option must be used to enable it. ``` set_option backward.grind.inferPattern false ``` Users can inspect differences between the old a new procedures using the option ``` set_option backward.grind.checkInferPatternDiscrepancy true ``` Example: ```lean /-- warning: found discrepancy between old and new `grind` pattern inference procedures, old: [@List.length #2 (@toList _ #1 #0)] new: [@toList #2 #1 #0] use `set_option backward.grind.inferPattern true` to force old procedure -/ #guard_msgs in set_option backward.grind.checkInferPatternDiscrepancy true in @[grind] theorem Vector.length_toList' (xs : Vector α n) : xs.toList.length = n := by sorry ```
35 lines
1.3 KiB
Text
35 lines
1.3 KiB
Text
set_option warn.sorry false
|
||
namespace Test
|
||
set_option backward.grind.inferPattern false -- Force new pattern inference procedure
|
||
|
||
inductive Vector (α : Type) : Nat → Type where
|
||
| nil : Vector α 0
|
||
| cons (x : α) (xs : Vector α n) : Vector α (n + 1)
|
||
|
||
def Vector.ofList (xs : List α) (h : xs.length = n) : Vector α n :=
|
||
match n, xs with
|
||
| 0, [] => .nil
|
||
| (n + 1), x :: xs => .cons x (.ofList xs (by grind))
|
||
|
||
def Vector.toList (xs : Vector α n) : List α :=
|
||
match xs with
|
||
| .nil => []
|
||
| .cons x xs => x :: xs.toList
|
||
|
||
/-- info: length_toList: [@toList #2 #1 #0] -/
|
||
#guard_msgs (info) in
|
||
@[grind?] theorem Vector.length_toList (xs : Vector α n) : xs.toList.length = n := by sorry
|
||
|
||
def wrapper (f : Nat → Nat → List α → List α) (h : ∀ n m xs, xs.length = n → (f n m xs).length = m) :
|
||
(n m : Nat) → Vector α n → Vector α m :=
|
||
fun n m xs => Vector.ofList (f n m xs.toList) (by grind) -- apply h; apply Vector.length_toList) -- fails here: (by grind)
|
||
|
||
/--
|
||
warning: found discrepancy between old and new `grind` pattern inference procedures, old:
|
||
[@List.length #2 (@toList _ #1 #0)]
|
||
new:
|
||
[@toList #2 #1 #0]
|
||
-/
|
||
#guard_msgs in
|
||
set_option backward.grind.checkInferPatternDiscrepancy true in
|
||
@[grind] theorem Vector.length_toList' (xs : Vector α n) : xs.toList.length = n := by sorry
|