This PR adds the following features to `simp`: - A routine for simplifying `have` telescopes in a way that avoids quadratic complexity arising from locally nameless expression representations, like what #6220 did for `letFun` telescopes. Furthermore, simp converts `letFun`s into `have`s (nondependent lets), and we remove the #6220 routine since we are moving away from `letFun` encodings of nondependent lets. - A `+letToHave` configuration option (enabled by default) that converts lets into haves when possible, when `-zeta` is set. Previously Lean would need to do a full typecheck of the bodies of `let`s, but the `letToHave` procedure can skip checking some subexpressions, and it modifies the `let`s in an entire expression at once rather than one at a time. - A `+zetaHave` configuration option, to turn off zeta reduction of `have`s specifically. The motivation is that dependent `let`s can only be dsimped by let, so zeta reducing just the dependent lets is a reasonable way to make progress. The `+zetaHave` option is also added to the meta configuration. - When `simp` is zeta reducing, it now uses an algorithm that avoids complexity quadratic in the depth of the let telescope. - Additionally, the zeta reduction routines in `simp`, `whnf`, and `isDefEq` now all are consistent with how they apply the `zeta`, `zetaHave`, and `zetaUnused` configurations. The `letToFun` option is addressing a TODO in `getSimpLetCase` ("handle a block of nested let decls in a single pass if this becomes a performance problem"). Performance should be compared to before #8804, which temporarily disabled the #6220 optimizations for `letFun` telescopes. Good kernel performance depends on carefully handling the `have` encoding. Due to the way the kernel instantiates bvars (it does *not* beta reduce when instantiating), we cannot use congruence theorems of the form `(have x := v; f x) = (have x ;= v'; f' x)`, since the bodies of the `have`s will not be syntactically equal, which triggers zeta reduction in the kernel in `is_def_eq`. Instead, we work with `f v = f' v'`, where `f` and `f'` are lambda expressions. There is still zeta reduction, but only when converting between these two forms at the outset of the generated proof.
23 lines
575 B
Text
23 lines
575 B
Text
example (h : z = 9) : have x := 5; have y := 4; x + y = z := by
|
|
intro x
|
|
simp
|
|
guard_target =ₛ x + 4 = z
|
|
rw [h]
|
|
|
|
example (h : z = 9) : have x := 5; have y := 4; x + y = z := by
|
|
intro x
|
|
simp (config := { zetaDelta := true })
|
|
guard_target =ₛ 9 = z
|
|
rw [h]
|
|
|
|
example (h : z = 9) : have x := 5; have y := 4; x + y = z := by
|
|
intro x
|
|
simp [x]
|
|
guard_target =ₛ 9 = z
|
|
rw [h]
|
|
|
|
example (h : z = 9) : have x := 5; have y := 4; x + y = z := by
|
|
intro x
|
|
simp (config := { zetaDelta := true, zeta := false })
|
|
guard_target =ₛ have y := 4; 5 + y = z
|
|
rw [h]
|