This PR implements the new E-matching pattern inference heuristic for `grind`. It is not enabled yet. You can activate the new behavior using `set_option backward.grind.inferPattern false`. Here is a summary of the new behavior. * `[grind =]`, `[grind =_]`, `[grind _=_]`, `[grind <-=]`: no changes; we keep the current behavior. * `[grind ->]`, `[grind <-]`, `[grind =>]`, `[grind <=]`: we stop using the *minimal indexable subexpression* and instead use the first indexable one. * `[grind! <mod>]`: behaves like `[grind <mod>]` but uses the minimal indexable subexpression restriction. We generate an error if the user writes `[grind! =]`, `[grind! =_]`, `[grind! _=_]`, or `[grind! <-=]`, since there is no pattern search in these cases. * `[grind]`: it tries `=`, `=_`, `<-`, `->`, `<=`, `=>` with and without the minimal indexable subexpression restriction. For the ones that work, we generate a code action to encourage users to select the one they prefer. * `[grind!]`: it tries `<-`, `->`, `<=`, `=>` using the minimal indexable subexpression restriction. For the ones that work, we generate a code action to encourage users to select the one they prefer. * `[grind? <mod>]`: where `<mod>` is one of the modifiers above, it behaves like `[grind <mod>]` but also displays the pattern. Example: ```lean /-- info: Try these: • [grind =] for pattern: [f (g #0)] • [grind =_] for pattern: [r #0 #0] • [grind! ←] for pattern: [g #0] -/ #guard_msgs in @[grind] axiom fg₇ : f (g x) = r x x ```
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
|