Zulip Chat Archive
Stream: mathlib4
Topic: What does `simpa using foo` do?
Arien Malec (Nov 21 2022 at 20:30):
I'm trying to unwind a misbehaving simpa using foo tactic (red squiggly + "no goals to be solved" + "Goals accomplished :tada:"), and would like to see where the more primitive simplification is getting to...
Riccardo Brasca (Nov 21 2022 at 20:35):
If you get both "goal accomplished" and an error it can be a bug. Can you provide a #mwe?
Arien Malec (Nov 21 2022 at 20:47):
Doesn't feel like it -- I'm deep in the bowels of a port that's secondary to another port. Let me see if I can sorry some stuff to make an #mwe
Arien Malec (Nov 21 2022 at 20:49):
I get the error on both simpas here:
import Mathlib.Data.Option.Basic
import Mathlib.Data.Subtype
import Mathlib.Logic.Equiv.Defs
variable (e : Option α ≃ Option β)
private def remove_none_aux (x : α) : β := sorry
private theorem remove_none_aux_some {x : α} (h : ∃ x', e (some x) = some x') :
some (remove_none_aux e x) = e (some x) := sorry
private theorem remove_none_aux_none {x : α} (h : e (some x) = none) :
some (remove_none_aux e x) = e none := sorry
private theorem remove_none_aux_inv (x : α) : remove_none_aux e.symm (remove_none_aux e x) = x :=
Option.some_injective _
(by
cases h1 : e.symm (some (remove_none_aux e x)) <;> cases h2 : e (some x)
· rw [remove_none_aux_none _ h1]
exact (e.eq_symm_apply.mpr h2).symm
· rw [remove_none_aux_some _ ⟨_, h2⟩] at h1
simpa using h1
· rw [remove_none_aux_none _ h2] at h1
simpa using h1
· rw [remove_none_aux_some _ ⟨_, h1⟩]
rw [remove_none_aux_some _ ⟨_, h2⟩]
simp
)
But figuring out how to trigger this with a minimum of dependencies is going to be tricky. Let me work on it...
Junyan Xu (Nov 21 2022 at 20:52):
simpa using h1 is like simp followed by exact h1, so it's possible that simp already solves the goal and so exact h1 produce an error that there's "no goals to be solved".
Riccardo Brasca (Nov 21 2022 at 20:54):
What happen if you remove all the private?
Arien Malec (Nov 21 2022 at 20:54):
simp doesn't solve the goal, sadly
Riccardo Brasca (Nov 21 2022 at 20:54):
Also, a sorried def is always dangerous.
Junyan Xu (Nov 21 2022 at 20:55):
What does simp at h1 ⊢ gives you?
Arien Malec (Nov 21 2022 at 20:55):
No effect on removing the private declarations.
Riccardo Brasca (Nov 21 2022 at 20:56):
Can you remove the first sorry?
Arien Malec (Nov 21 2022 at 20:56):
I just sorryd to de-dependency the beast...
Arien Malec (Nov 21 2022 at 20:56):
Unfortunately the first sorry depends on a file that's as yet unported....
Arien Malec (Nov 21 2022 at 20:57):
@Junyan Xu 's suggestion gives the :tada:
Mario Carneiro (Nov 21 2022 at 20:58):
make them opaque instead of sorry
Mario Carneiro (Nov 21 2022 at 20:58):
or axiom
Arien Malec (Nov 21 2022 at 21:00):
OK, this repros.
import Mathlib.Data.Option.Basic
import Mathlib.Data.Subtype
import Mathlib.Logic.Equiv.Defs
variable (e : Option α ≃ Option β)
def remove_none_aux (x : α) : β :=
if h : (e (some x)).isSome then Option.get _ h
else
Option.get _ <|
show (e none).isSome by
rw [← Option.ne_none_iff_isSome]
intro hn
rw [Option.not_isSome_iff_eq_none, ← hn] at h
exact Option.some_ne_none _ (e.injective h)
theorem remove_none_aux_some {x : α} (h : ∃ x', e (some x) = some x') :
some (remove_none_aux e x) = e (some x) :=
by simp [remove_none_aux, Option.isSome_iff_exists.mpr h]
theorem remove_none_aux_none {x : α} (h : e (some x) = none) :
some (remove_none_aux e x) = e none := by
simp [remove_none_aux, Option.not_isSome_iff_eq_none.mpr h]
theorem remove_none_aux_inv (x : α) : remove_none_aux e.symm (remove_none_aux e x) = x :=
Option.some_injective _
(by
cases h1 : e.symm (some (remove_none_aux e x)) <;> cases h2 : e (some x)
· rw [remove_none_aux_none _ h1]
exact (e.eq_symm_apply.mpr h2).symm
· rw [remove_none_aux_some _ ⟨_, h2⟩] at h1
simpa using h1
· rw [remove_none_aux_none _ h2] at h1
simpa using h1
· rw [remove_none_aux_some _ ⟨_, h1⟩]
rw [remove_none_aux_some _ ⟨_, h2⟩]
simp
)
Ruben Van de Velde (Nov 21 2022 at 21:06):
When I've hit that, replacing simpa using foo by simp at foo was sufficient
Arien Malec (Nov 21 2022 at 21:08):
So interestingly, when I replace
simpa using h1
with
simp at h1
exact h1
I get the same behavior (red squiggly + :tada:)
Mario Carneiro (Nov 21 2022 at 21:08):
what it macro expands to is:
have' h := h1
simp at h1
exact h
and the exact line fails. As Ruben says, the solution is to just use simp at h1, the error message should be fixed to indicate this
Mario Carneiro (Nov 21 2022 at 21:09):
The red squiggly + :tada: situation isn't that unusual, the tactic state is generally empty at the end of a proof and that's when the :tada: shows up
Mario Carneiro (Nov 21 2022 at 21:10):
in particular, almost all tactics give an error if used when there are no goals, and that's when you get the :tada:
Arien Malec (Nov 21 2022 at 21:10):
It's just that h1is the goal....
Mario Carneiro (Nov 21 2022 at 21:10):
?
Arien Malec (Nov 21 2022 at 21:10):
so exact h1 should work?
Mario Carneiro (Nov 21 2022 at 21:11):
no, h1 is not the goal
Mario Carneiro (Nov 21 2022 at 21:11):
h1 is some ... = none after simplification which is why simp can close the goal itself
Arien Malec (Nov 21 2022 at 21:12):
If I take the #mwe above, replace simpa using h1 with simp at h1, h1 is the goal...
Mario Carneiro (Nov 21 2022 at 21:12):
I think you must be confused by the "expected type" printout
Mario Carneiro (Nov 21 2022 at 21:12):
the tactic state is empty (i.e. there are no goals and you get a :tada:)
Mario Carneiro (Nov 21 2022 at 21:12):
that's the first bit
Mario Carneiro (Nov 21 2022 at 21:12):
the expected type is the type of h1
Mario Carneiro (Nov 21 2022 at 21:12):
because your cursor is on h1
Arien Malec (Nov 21 2022 at 21:14):
You are exactly correct
Last updated: May 02 2025 at 03:31 UTC