This PR introduces a new `grind` option, `funCC` (enabled by default),
which extends congruence closure to *function-valued* equalities. When
`funCC` is enabled, `grind` tracks equalities of **partially applied
functions**, allowing reasoning steps such as:
```lean
a : Nat → Nat
f : (Nat → Nat) → (Nat → Nat)
h : f a = a
⊢ (f a) m = a m
g : Nat → Nat
f : Nat → Nat → Nat
h : f a = g
⊢ f a b = g b
```
Given an application `f a₁ a₂ … aₙ`, when `funCC := true` and function
equality is enabled for `f`, `grind` generates and tracks equalities for
all partial applications:
* `f a₁`
* `f a₁ a₂`
* …
* `f a₁ a₂ … aₙ`
This allows equalities such as `f a₁ = g` to propagate through further
applications.
**When is function equality enabled for a symbol?**
Function equality is enabled for `f` in the following cases:
1. `f` is **not a constant** (e.g., a lambda, a local function, or a
function parameter).
2. `f` is a **structure field projection**, provided the structure is
**not a `class`**.
3. `f` is a constant marked with `@[grind funCC]`
Users can also enable function equality for specific constants in a
single call using:
```lean
grind [funCC f, funCC g]
```
**Examples:**
```lean
example (m : Nat) (a : Nat → Nat) (f : (Nat → Nat) → (Nat → Nat)) (h : f a = a) :
f a m = a m := by
grind
example (m : Nat) (a : Nat → Nat) (f : (Nat → Nat) → (Nat → Nat)) (h : f a = a) :
f a m = a m := by
fail_if_success grind -funCC -- fails if `funCC` is disabled
grind
```
```lean
example (a b : Nat) (g : Nat → Nat) (f : Nat → Nat → Nat) (h : f a = g) :
f a b = g b := by
grind
example (a b : Nat) (g : Nat → Nat) (f : Nat → Nat → Nat) (h : f a = g) :
f a b = g b := by
fail_if_success grind -funCC
grind
```
**Enabling per-symbol with parameters or attributes**
```lean
opaque f : Nat → Nat → Nat
opaque g : Nat → Nat
example (a b c : Nat) : f a = g → b = c → f a b = g c := by
grind [funCC f, funCC g]
attribute [grind funCC] f g
example (a b c : Nat) : f a = g → b = c → f a b = g c := by
grind
```
This feature substantially improves `grind`’s support for higher-order
and partially-applied function equalities, while preserving
compatibility with first-order SMT behavior when `funCC` is disabled.
Closes #11309
94 lines
1.8 KiB
Text
94 lines
1.8 KiB
Text
import Lean
|
|
|
|
example (m : Nat) (a b : Nat → Nat) (h : b = a) :
|
|
b m = a m := by
|
|
grind
|
|
|
|
example (m n : Nat) (a b : Nat → Nat → Nat) : b = a → m = n → i = j → b m i = a n j := by
|
|
grind
|
|
|
|
example (m : Nat) (a : Nat → Nat) (f : (Nat → Nat) → (Nat → Nat)) (h : f a = a) :
|
|
f a m = a m := by
|
|
grind
|
|
|
|
example (m : Nat) (a : Nat → Nat) (f : (Nat → Nat) → (Nat → Nat)) (h : f a = a) :
|
|
f a m = a m := by
|
|
fail_if_success grind -funCC
|
|
grind
|
|
|
|
example (a b : Nat) (g : Nat → Nat) (f : Nat → Nat → Nat) (h : f a = g) :
|
|
f a b = g b := by
|
|
grind
|
|
|
|
example (a b : Nat) (g : Nat → Nat) (f : Nat → Nat → Nat) (h : f a = g) :
|
|
f a b = g b := by
|
|
fail_if_success grind -funCC
|
|
grind
|
|
|
|
namespace WithStructure
|
|
|
|
structure Test where
|
|
apply: Unit → Prop
|
|
|
|
def test : Test := {
|
|
apply := fun () => True
|
|
}
|
|
|
|
example : test.apply () := by
|
|
grind [test]
|
|
|
|
end WithStructure
|
|
|
|
-- grind succeeds without the thunk
|
|
namespace WithoutThunk
|
|
|
|
structure Test where
|
|
apply: Prop
|
|
|
|
def test : Test := {
|
|
apply := True
|
|
}
|
|
|
|
example : test.apply := by
|
|
grind [test]
|
|
|
|
end WithoutThunk
|
|
|
|
-- grind succeeds without structure
|
|
namespace WithoutStructure
|
|
|
|
def Test := Unit → Prop
|
|
|
|
def test : Test := fun () => True
|
|
|
|
example : test () := by
|
|
grind [test]
|
|
|
|
end WithoutStructure
|
|
|
|
namespace Ex
|
|
|
|
opaque f : Nat → Nat → Nat
|
|
opaque g : Nat → Nat
|
|
|
|
example (a b c : Nat) : f a = g → b = c → f a b = g c := by
|
|
fail_if_success grind
|
|
simp_all
|
|
|
|
example (a b c : Nat) : f a = g → b = c → f a b = g c := by
|
|
grind [funCC f, funCC g]
|
|
|
|
example (a b c : Nat) : f a = g → b = c → f a b = g c := by
|
|
fail_if_success grind
|
|
simp_all
|
|
|
|
attribute [grind funCC] f g
|
|
|
|
example (a b c : Nat) : f a = g → b = c → f a b = g c := by
|
|
grind
|
|
|
|
example (a b c : Nat) : f a = g → b = c → f a b = g c := by
|
|
fail_if_success grind -funCC
|
|
grind
|
|
|
|
end Ex
|