Formal Software Verification

4.5. Rewriting Tactics🔗

The tactic rw applies an equation as a left-to-right rewrite rule, once. It finds the first subterm that matches the left-hand side, instantiates the variables of the equation accordingly, replaces every occurrence of that instantiated subterm, and then tries rfl. A leading uses the equation right to left, at h rewrites the hypothesis h instead of the conclusion, and at * rewrites everywhere. Given a constant name instead of an equation, rw uses the defining equations of the constant, which is how rw [Not] expands a negation and rw [add] unfolds our add.

namespace Backward theorem Eq_trans_symm_rw {α : Type} (a b c : α) (hab : a = b) (hcb : c = b) : a = c := α:Typea:αb:αc:αhab:a = bhcb:c = ba = c α:Typea:αb:αc:αhab:a = bhcb:c = bb = c All goals completed! 🐙 theorem a_proof_of_negation (a : Prop) : a ¬¬ a := a:Propa ¬¬a a:Propa ¬a False a:Propa (a False) False a:Propha:ahna:a FalseFalse a:Propha:ahna:a Falsea All goals completed! 🐙 end Backward

The tactic simp applies a standard set of rewrite rules, the simp set, exhaustively. The syntax simp [t₁, …, tₙ] adds theorems or constants for one invocation, simp [-t] removes one, simp [*] at * uses every hypothesis on every hypothesis and on the conclusion, and the attribute @[simp] registers a theorem permanently.

namespace Backward theorem cong_two_args_1p1 {α : Type} (a b c d : α) (g : α α α) (hab : a = b) (hcd : c = d) : g a c (1 + 1) = g b d 2 := α:Typea:αb:αc:αd:αg:α α αhab:a = bhcd:c = dg a c (1 + 1) = g b d 2 All goals completed! 🐙 end Backward

Rewriting is where proofs stop being predictable. The guide's advice is to try a tactic, study the subgoals that emerge, and adjust, rather than to plan every step in advance. In the guide's own words, DON'T PANIC.

4.5.1. Examples🔗

The examples below rewrite in the conclusion and in the hypotheses, in both directions, and compare rw with simp on the same goal.

Example 1. rw [h] rewrites the conclusion left to right and closes it with the rfl it tries at the end.

example (f : ) (a b : ) (h : a = b) : f a = f b := f: a:b:h:a = bf a = f b All goals completed! 🐙

Example 2. rw [←h] uses the same equation right to left.

example (f : ) (a b : ) (h : a = b) : f b = f a := f: a:b:h:a = bf b = f a All goals completed! 🐙

Example 3. rw [h₁, h₂] applies two equations in turn.

example (a b c : ) (h₁ : a = b) (h₂ : b = c) : a = c := a:b:c:h₁:a = bh₂:b = ca = c All goals completed! 🐙

Example 4. rw [h₂] at h₁ rewrites the hypothesis, and the rewritten hypothesis closes the goal.

example (a b c : ) (h₁ : a = b) (h₂ : b = c) : a = c := a:b:c:h₁:a = bh₂:b = ca = c a:b:c:h₁:a = ch₂:b = ca = c All goals completed! 🐙

Example 5. rw closes the goal on its own once the two sides coincide, because it tries rfl after rewriting.

example (a b : ) (h : a = b) : a = b := a:b:h:a = ba = b All goals completed! 🐙

Example 6. rw [add] unfolds a defining equation of our add.

example (m n : ) : add m (Nat.succ n) = Nat.succ (add m n) := m:n:add m n.succ = (add m n).succ All goals completed! 🐙

Example 7. rw [Not] at h expands the negation in a hypothesis, which then applies as an implication.

example (a : Prop) (h : ¬a) : a False := a:Proph:¬aa False a:Proph:a Falsea False All goals completed! 🐙

Example 8. simp alone closes an arithmetic goal from the default simp set.

example (n : ) : n + 0 + 0 = n := n:n + 0 + 0 = n All goals completed! 🐙

Example 9. simp [h] rewrites every occurrence, where rw [h] rewrites only the occurrences of the first matching subterm. The first script needs two rewrites, one per instance of the pattern, and the second needs one simp.

example (f : ) (hf : x, f x = 0) : f 1 + f 2 = 0 := f: hf: (x : ), f x = 0f 1 + f 2 = 0 f: hf: (x : ), f x = 00 + f 2 = 0 All goals completed! 🐙 example (f : ) (hf : x, f x = 0) : f 1 + f 2 = 0 := f: hf: (x : ), f x = 0f 1 + f 2 = 0 All goals completed! 🐙

Example 10. simp [*] at * uses every hypothesis everywhere and closes a goal from two chained hypotheses.

example (a b c : ) (h₁ : a = b) (h₂ : b = c) : a = c := a:b:c:h₁:a = bh₂:b = ca = c All goals completed! 🐙