Zulip Chat Archive
Stream: lean4
Topic: mutate subgoal environment
Enrico Borba (Jan 13 2024 at 19:53):
I'm in the middle of a tactic proof that looks like this:
match s with
| .or =>
have hff₁₂ : ∀ b, f b = Bool.or (f₁ b) (f₂ b) := sorry
simp only [Model.value, Interpretation.fns]
conv at ih₁ => lhs; simp only [Dual.dual]
conv at ih₂ => lhs; simp only [Dual.dual]
rw [ih₁, ih₂]
simp only [Dual.dual, Signature.Formula.function]
rw [(by rfl : ~w.vec = (~w).vec), hf₁ (~w), hf₂ (~w), hff₁₂]
simp only [Bool.not_or, Bool.not_and]
| .and =>
have hff₁₂ : ∀ b, f b = Bool.and (f₁ b) (f₂ b) := sorry
simp only [Model.value, Interpretation.fns]
conv at ih₁ => lhs; simp only [Dual.dual]
conv at ih₂ => lhs; simp only [Dual.dual]
rw [ih₁, ih₂]
simp only [Dual.dual, Signature.Formula.function]
rw [(by rfl : ~w.vec = (~w).vec), hf₁ (~w), hf₂ (~w), hff₁₂]
simp only [Bool.not_or, Bool.not_and]
Notice the proofs in each of the two arms are the same except for the first line. This first line in each arm introduces a new term into each of the arms' environments. Is there a way to do this and then "return" to the top level? I'm imagining some code like this:
match s with
| .or => have hff₁₂ : ∀ b, f b = Bool.or (f₁ b) (f₂ b) := sorry
| .and => have hff₁₂ : ∀ b, f b = Bool.and (f₁ b) (f₂ b) := sorry
/-
The two cases `and` and `or` would then return to being subgoals as they
are not resolved(?) yet.
-/
all_goals {
simp only [Model.value, Interpretation.fns]
conv at ih₁ => lhs; simp only [Dual.dual]
conv at ih₂ => lhs; simp only [Dual.dual]
rw [ih₁, ih₂]
simp only [Dual.dual, Signature.Formula.function]
rw [(by rfl : ~w.vec = (~w).vec), hf₁ (~w), hf₂ (~w), hff₁₂]
simp only [Bool.not_or, Bool.not_and]
}
Joachim Breitner (Jan 13 2024 at 21:46):
May not apply in your case, but if the goals are the same after these lines(not just the tactics), and it's not too bad to spell it out, you can manually have
the goal before the case, and then use assumption
in the cases.
Kyle Miller (Jan 13 2024 at 22:30):
Or, rather than using match
, you could use cases
followed by case'
blocks.
Maybe something like this:
cases s
case' or =>
have hff₁₂ : ∀ b, f b = Bool.or (f₁ b) (f₂ b) := sorry
case' and =>
have hff₁₂ : ∀ b, f b = Bool.and (f₁ b) (f₂ b) := sorry
all_goals
simp only [Model.value, Interpretation.fns]
conv at ih₁ => lhs; simp only [Dual.dual]
conv at ih₂ => lhs; simp only [Dual.dual]
rw [ih₁, ih₂]
simp only [Dual.dual, Signature.Formula.function]
rw [(by rfl : ~w.vec = (~w).vec), hf₁ (~w), hf₂ (~w), hff₁₂]
simp only [Bool.not_or, Bool.not_and]
Kyle Miller (Jan 13 2024 at 22:31):
If you're using match
for recursion, maybe you could use induction
instead of cases
. You might also be able to set up using some named metavariables in conjunction with refine match s with ...
and do something like this case'
option.
Enrico Borba (Jan 13 2024 at 22:38):
oh does case'
not fail if the sub goals aren't resolved?
Kyle Miller (Jan 13 2024 at 22:45):
Yes. Here's its docstring:
case'
is similar to thecase tag => tac
tactic, but does not ensure the goal has been solved after applyingtac
, nor admits the goal iftac
failed. Recall thatcase
closes the goal using sorry whentac
fails, and the tactic execution is not interrupted.
Enrico Borba (Jan 13 2024 at 22:53):
Sweet, that's basically what I was looking for. Thanks!
Last updated: May 02 2025 at 03:31 UTC