@@ -24,30 +24,22 @@ e : Prime (2 * n + 1)
2424⊢ Prime (n + n + 1)
2525```
2626
27- the tactic `convert e using 2 ` will change the goal to
27+ the tactic `convert e` will change the goal to
2828
2929```lean
3030⊢ n + n = 2 * n
3131```
3232
3333In this example, the new goal can be solved using `ring`.
3434
35- The `using 2` indicates it should iterate the congruence algorithm up to two times,
36- where `convert e` would use an unrestricted number of iterations and lead to two
37- impossible goals: `⊢ HAdd.hAdd = HMul.hMul` and `⊢ n = 2`.
38-
39- A variant configuration is `convert (config := .unfoldSameFun) e`, which only equates function
40- applications for the same function (while doing so at the higher `default` transparency).
41- This gives the same goal of `⊢ n + n = 2 * n` without needing `using 2`.
42-
4335The `convert` tactic applies congruence lemmas eagerly before reducing,
4436therefore it can fail in cases where `exact` succeeds:
4537```lean
4638def p (n : ℕ) := True
4739example (h : p 0) : p 1 := by exact h -- succeeds
4840example (h : p 0) : p 1 := by convert h -- fails, with leftover goal `1 = 0`
4941```
50- Limiting the depth of recursion can help with this. For example, `convert h using 1 ` will work
42+ Limiting the depth of recursion can help with this. For example, `convert h using 0 ` will work
5143in this case.
5244
5345The syntax `convert ← e` will reverse the direction of the new goals
@@ -85,21 +77,12 @@ between `Convert.CheapConfig` and `Convert.ExpensiveConfig` based on other flags
8577-/
8678structure Convert.CheapConfig extends Congr!.Config where
8779 postTransparency := .reducible
80+ partialApp := false
81+ sameFun := true
8882
8983/-- Internal elaborator for `Convert.CheapConfig`: use `Convert.elabConfig` instead. -/
9084declare_config_elab Convert.elabCheapConfig Convert.CheapConfig
9185
92- /-- A configuration option that makes `convert` do the sorts of aggressive unfoldings that `congr`
93- does while also similarly preventing `convert` from considering partial applications or congruences
94- between different functions being applied.
95-
96- Note that `convert (config := .unfoldSameFun)` and `convert! (config := .unfoldSameFun)`
97- currently do the same thing since `.unfoldSameFun` runs at default transparency always.
98- This may change in the future, if `convert!` affects other options too.
99- -/
100- abbrev Convert.CheapConfig.unfoldSameFun : Convert.CheapConfig :=
101- { Congr!.Config.unfoldSameFun with }
102-
10386/-- Configuration for the `convert!` family of tactics.
10487This is `Convert.CheapConfig` (used by `convert` without exclamation mark) with different,
10588more aggressive, defaults.
@@ -113,26 +96,14 @@ example the following call runs at `.instances` transparency.
11396convert! (postTransparency := .instances)
11497```
11598-/
116- structure Convert.ExpensiveConfig extends Convert.CheapConfig where
99+ structure Convert.ExpensiveConfig extends Congr!.Config where
117100 -- TODO: also enable this in the future?
118101 -- preTransparency := .default
119102 -- transparency := .default
120- postTransparency := .default
121103
122104/-- Internal elaborator for `Convert.ExpensiveConfig`: use `Convert.elabConfig` instead. -/
123105declare_config_elab Convert.elabExpensiveConfig Convert.ExpensiveConfig
124106
125- /-- A configuration option that makes `convert!` do the sorts of aggressive unfoldings that `congr`
126- does while also similarly preventing `convert!` from considering partial applications or congruences
127- between different functions being applied.
128-
129- Note that `convert (config := .unfoldSameFun)` and `convert! (config := .unfoldSameFun)`
130- currently do the same thing since `.unfoldSameFun` runs at default transparency always.
131- This may change in the future, if `convert!` affects other options too.
132- -/
133- abbrev Convert.ExpensiveConfig.unfoldSameFun : Convert.ExpensiveConfig :=
134- { Congr!.Config.unfoldSameFun with }
135-
136107/-- Configuration elaborator for the `convert`/`convert!` family of tactics.
137108
138109If `expensive` is true, we're elaborating for `convert!`, and will configure to run at default
@@ -201,9 +172,10 @@ pattern-matched, like `rintro` would, using the `with` keyword.
201172See also `convert_to t`, where `t` specifies the expected type, instead of a proof term of type `t`.
202173In other words, `convert_to t` works like `convert (?_ : t)`. Both tactics use the same options.
203174
204- * `convert! e` uses default transparency, rather than reducible, when solving side goals.
175+ * `convert! e` uses default transparency, rather than reducible, when solving side goals, and
176+ it tries to apply congruence even if the two expressions do not have the same head constant.
205177* `convert ← e` creates equality goals in the opposite direction (with the goal type on the right).
206- * `convert e using n`, where `n` is a positive numeral, controls the depth with which congruence is
178+ * `convert e using n`, where `n` is a numeral, controls the depth with which congruence is
207179 applied. For example, if the main goal is `⊢ Prime (n + n + 1)` and `e : Prime (2 * n + 1)`, then
208180 `convert e using 2` results in one goal, `⊢ n + n = 2 * n`, and `convert e using 3` (or more)
209181 results in two (impossible) goals `⊢ HAdd.hAdd = HMul.hMul` and `⊢ n = 2`.
@@ -216,10 +188,9 @@ In other words, `convert_to t` works like `convert (?_ : t)`. Both tactics use t
216188 Examples:
217189
218190```lean
219- -- `convert using` controls the depth of congruence.
220191example {n : ℕ} (e : Prime (2 * n + 1)) :
221192 Prime (n + n + 1) := by
222- convert e using 2
193+ convert e
223194 -- One goal: ⊢ n + n = 2 * n
224195 ring
225196
@@ -234,7 +205,7 @@ example (h : p 0) : p 1 := by
234205-- `convert with` names introduced variables.
235206example (p q : Nat → Prop) (h : ∀ ε > 0, p ε) :
236207 ∀ ε > 0, q ε := by
237- convert h using 2 with ε hε
208+ convert h with ε hε
238209 -- Goal now looks like:
239210 -- hε : ε > 0
240211 -- ⊢ q ε ↔ p ε
0 commit comments