You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Manual/Grind/EMatching.lean
+40Lines changed: 40 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -87,6 +87,13 @@ grind_pattern $_ => $_,*
87
87
```
88
88
Associates a theoremwith one or more patterns.
89
89
When multiple patterns are provided in a single {keywordOf Lean.Parser.Command.grind_pattern}`grind_pattern` command, _all_ of them must match a term before {tactic}`grind` will attempt to instantiate the theorem.
90
+
91
+
```grammar
92
+
grind_pattern $_ => $_,* where $_
93
+
```
94
+
The optional {keywordOf Lean.Parser.Command.grind_pattern}`where` clause specifies constraints that must be satisfied before {tactic}`grind` attempts to instantiate the theorem.
95
+
Each constraint has the form `variable =/= value`, preventing instantiation when the pattern variable would be assigned the specified value.
96
+
This is useful to avoid unbounded or excessive instantiations with problematic terms.
90
97
:::
91
98
92
99
::::example"Selecting Patterns"
@@ -183,6 +190,39 @@ The multi-pattern `R x y, R y z` instructs {tactic}`grind` to instantiate {lean}
183
190
In the example, {tactic}`grind` applies {lean}`Rtrans` to derive {lean}`R a c` from {lean}`R a b` and {lean}`R b c`, and can then repeat the same reasoning to deduce {lean}`R a d` from {lean}`R a c` and {lean}`R c d`.
184
191
::::
185
192
193
+
::::example"Pattern Constraints"
194
+
Certain combinations of theorems can lead to unbounded instantiation, where E-matching repeatedly generates longer and longer terms.
195
+
Consider theorems about {name}`List.flatMap` and {name}`List.reverse`.
196
+
If {name}`List.flatMap_def`, {name}`List.flatMap_reverse`, and {name}`List.reverse_flatMap` are all annotated with {attrs}`@[grind =]`, then as soon as {name}`List.flatMap_reverse` is instantiated, the following chain of instantiations occurs, creating progressively longer function compositions with {name}`List.reverse`.
197
+
This can be observed using the `#grind_lint` command:
198
+
```
199
+
attribute [local grind =] List.reverse_flatMap
200
+
201
+
set_option trace.grind.ematch.instance truein
202
+
#grind_lint inspect List.flatMap_reverse
203
+
```
204
+
The trace output shows the unbounded instantiation:
This pattern continues indefinitely, with each iteration adding another {lean}`List.reverse` to the composition.
216
+
The {keywordOf Lean.Parser.Command.grind_pattern}`where` clause prevents this by excluding problematic instantiations:
217
+
```
218
+
grind_pattern reverse_flatMap => (l.flatMap f).reverse where
219
+
f =/= List.reverse ∘ _
220
+
```
221
+
This instructs {tactic}`grind` to use the pattern `(l.flatMap f).reverse`, but only when `f` is not a composition with {name}`List.reverse`, preventing the unbounded chain of instantiations.
222
+
223
+
You can use `#grind_lint check` to look for problematic patterns, or `#grind_lint check in List` or`#grind_lint check in module Std.Data` to look in specific namespaces or modules.
224
+
::::
225
+
186
226
The {attr}`grind` attribute automatically generates an E-matching pattern or multi-pattern using a heuristic, instead of using {keywordOf Lean.Parser.Command.grindPattern}`grind_pattern` to explicitly specify a pattern.
187
227
It includes a number of variants that select different heuristics.
188
228
The {attr}`grind?` attribute displays an info message showing the pattern which was selected—this is very helpful for debugging!
0 commit comments