Congruence and related tactics
This file contains the tactic congr', which is an extension of congr, and various tactics
using congr' internally.
congr' has some advantages over congr:
- It turns
↔to equalities, before trying another congr lemma - You can write
congr' nto give the maximal depth of recursive applications. This is useful ifcongrbreaks down the goal to aggressively, and the resulting goals are false. - You can write
congr' with ...to docongr', ext ...in a single tactic.
Other tactics in this file:
rcongr: repeatedly applycongr'andext.convert: likeexact, but produces an equality goal if the type doesn't match.convert_to: changes the goal, if you prove an equality between the old goal and the new goal.ac_change: likeconvert_to, but usesac_reflto discharge the goals.
The main part of the body for the loop in congr'. This will try to replace a goal f x = f y
with x = y. Also has support for == and ↔.
The main function in convert_to. Changes the goal to r and a proof obligation that the goal
is equal to r.
Same as the congr tactic, but takes an optional argument which gives
the depth of recursive applications.
- This is useful when
congris too aggressive in breaking down the goal. - For example, given
⊢ f (g (x + y)) = f (g (y + x)),congr'produces the goals⊢ x = yand⊢ y = x, whilecongr' 2produces the intended⊢ x + y = y + x. - If, at any point, a subgoal matches a hypothesis then the subgoal will be closed.
Same as the congr tactic, but takes an optional argument which gives
the depth of recursive applications.
- This is useful when
congris too aggressive in breaking down the goal. - For example, given
⊢ f (g (x + y)) = f (g (y + x)),congr'produces the goals⊢ x = yand⊢ y = x, whilecongr' 2produces the intended⊢ x + y = y + x. - If, at any point, a subgoal matches a hypothesis then the subgoal will be closed.
- You can use
congr' with p (: n)?to callext p (: n)?to all subgoals generated bycongr'. For example, if the goal is⊢ f '' s = g '' sthencongr' with xgenerates the goalx : α ⊢ f x = g x.
Repeatedly and apply congr' and ext, using the the given patterns as arguments for ext.
There are two ways this tactic stops:
congr'fails (makes no progress), after having already appliedext.congr'canceled out the last usage ofext. In this case, the state is reverted to before thecongr'was applied.
For example, when the goal is
⊢ (λ x, f x + 3) '' s = (λ x, g x + 3) '' s
then rcongr x produces the goal
x : α ⊢ f x = g x
This gives the same result as congr', ext x, congr'.
In contrast, congr' would produce
⊢ (λ x, f x + 3) = (λ x, g x + 3)
and congr' with x (or congr', ext x) would produce
x : α ⊢ f x + 3 = g x + 3
The exact e and refine e tactics require a term e whose type is
definitionally equal to the goal. convert e is similar to refine
e, but the type of e is not required to exactly match the
goal. Instead, new goals are created for differences between the type
of e and the goal. For example, in the proof state
the tactic convert e will change the goal to
⊢ n + n = 2 * n
In this example, the new goal can be solved using ring.
If x y : t, and an instance subsingleton t is in scope, then any goals of the form
x = y are solved automatically.
The syntax convert ← e will reverse the direction of the new goals
(producing ⊢ 2 * n = n + n in this example).
Internally, convert e works by creating a new goal asserting that
the goal equals the type of e, then simplifying it using
congr'. The syntax convert e using n can be used to control the
depth of matching (like congr' n). In the example, convert e using
1 would produce a new goal ⊢ n + n + 1 = 2 * n + 1.
convert_to g using n attempts to change the current goal to g, but unlike change,
it will generate equality proof obligations using congr' n to resolve discrepancies.
convert_to g defaults to using congr' 1.
ac_change is convert_to followed by ac_refl. It is useful for rearranging/reassociating
e.g. sums:
example (a b c d e f g N : ℕ) : (a + b) + (c + d) + (e + f) + g ≤ N :=
begin
ac_change a + d + e + f + c + g + b ≤ _,
-- ⊢ a + d + e + f + c + g + b ≤ N
end
ac_change g using n is convert_to g using n; try {ac_refl}.