This PR replaces the `grind` canonicalizer with a new type-directed normalizer (`Sym.canon`) that goes inside binders and applies targeted reductions in type positions, eliminating the O(n^2) `isDefEq`-based approach. The old canonicalizer maintained a map from `(function, argument_position)` to previously seen arguments, iterating the list and calling `isDefEq` for each new argument. This produced performance problems in some goal. For example, for a goal containing `n` numeric literals, it would produce O(n^2) `isDefEq` comparisons. The new canonicalizer normalizes types directly: - **Instances**: re-synthesized via `synthInstance` with the type normalized first, so `OfNat (Fin (2+1)) 0` and `OfNat (Fin 3) 0` produce the same instance. - **Types**: normalized with targeted reductions — eta, projection, match/ite/cond, and Nat arithmetic (`n.succ + 1` → `n + 2`, `2 + 1` → `3`). - **Values**: traversed but not reduced, preserving lambdas for grind's beta module. The canonicalizer enters binders (the old one did not), using separate caches for type-level and value-level contexts. Propositions are not normalized to avoid interfering with grind's proposition handling. Move `SynthInstance` from `Grind` to `Sym` since the canonicalizer now lives in `Sym` and needs instance synthesis. The `Grind` namespace re-exports the key functions. Add `no_index` annotations to `val_addNat` and `val_castAdd` patterns in `Fin/Lemmas.lean` — arithmetic in type positions is now normalized, so patterns must not rely on the un-normalized form for e-matching indexing. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
39 lines
1.2 KiB
Text
39 lines
1.2 KiB
Text
module
|
||
def List.Disjoint (l₁ l₂ : List α) : Prop :=
|
||
∀ ⦃a⦄, a ∈ l₁ → a ∈ l₂ → False
|
||
|
||
|
||
/--
|
||
error: `grind` failed
|
||
case grind
|
||
i n : Nat
|
||
f : Nat → List (List Nat)
|
||
l : List Nat
|
||
h :
|
||
¬List.Pairwise
|
||
(fun x y =>
|
||
(if x ^ i ≤ n then List.map (List.cons x) (f x) else []).Disjoint
|
||
(if y ^ i ≤ n then List.map (List.cons y) (f y) else []))
|
||
l
|
||
⊢ False
|
||
[grind] Goal diagnostics
|
||
[facts] Asserted facts
|
||
[prop] ¬List.Pairwise
|
||
(fun x y =>
|
||
(if x ^ i ≤ n then List.map (List.cons x) (f x) else []).Disjoint
|
||
(if y ^ i ≤ n then List.map (List.cons y) (f y) else []))
|
||
l
|
||
[eqc] False propositions
|
||
[prop] List.Pairwise
|
||
(fun x y =>
|
||
(if x ^ i ≤ n then List.map (List.cons x) (f x) else []).Disjoint
|
||
(if y ^ i ≤ n then List.map (List.cons y) (f y) else []))
|
||
l
|
||
-/
|
||
#guard_msgs in
|
||
theorem test (f : Nat → List (List Nat)) {l : List Nat} :
|
||
l.Pairwise
|
||
(fun x y ↦
|
||
(if x ^ i ≤ n then List.map (fun m ↦ x :: m) (f x) else []).Disjoint
|
||
(if y ^ i ≤ n then List.map (fun m ↦ y :: m) (f y) else [])) := by
|
||
grind
|