Zulip Chat Archive
Stream: lean4
Topic: Why do `cases` and `induction ... using` differ
Leni Aniva (Mar 18 2025 at 21:04):
e.g.
theorem ex_cases_or (p : Prop) (hpp : p ∨ p) : p := by
cases hpp <;> assumption
#print ex_cases_or
theorem ex_induction_or (p : Prop) (hpp : p ∨ p) : p := by
induction hpp using Or.casesOn <;> assumption
#print ex_induction_or
In this case, the expressions are
theorem ex_cases_or : ∀ (p : Prop), p ∨ p → p :=
fun p hpp => Or.casesOn (motive := fun t => hpp = t → p) hpp (fun h h_1 => h) (fun h h_1 => h) (Eq.refl hpp)
theorem ex_induction_or : ∀ (p : Prop), p ∨ p → p :=
fun p hpp => Or.casesOn hpp (fun h => h) fun h => h
In Lean/Meta/Tactic/Cases.lean
, cases
calls induction
in its implementation, so why does it behave differently?
Kyle Miller (Mar 18 2025 at 21:46):
The situation is that they both use the same underlying framework, which happens to use "induction" in the name, but both cases
and induction
are different frontends to this backend.
They both use the same underlying framework, but cases
can handle indexed inductive types where the indices aren't variables. It basically does generalize
on all the indices for you automatically. I'm not sure why this restriction is in place exactly. Maybe it's because otherwise the inductive hypotheses will have all these additional equality hypotheses? Or maybe it could be done but induction
would need to work out which of these generalized variables should be added to the generalizing
clause, and that hasn't been done yet?
It looks like the difference in your examples is from cases
not being efficient with its generalizations.
Jad Ghalayini (Mar 18 2025 at 22:57):
On a related note, is there any way to make induction
do the generalization?
Kyle Miller (Mar 18 2025 at 23:12):
Unfortunately no, you have to generalize
manually.
Leni Aniva (Mar 19 2025 at 07:55):
Kyle Miller said:
The situation is that they both use the same underlying framework, which happens to use "induction" in the name, but both
cases
andinduction
are different frontends to this backend.They both use the same underlying framework, but
cases
can handle indexed inductive types where the indices aren't variables. It basically doesgeneralize
on all the indices for you automatically. I'm not sure why this restriction is in place exactly. Maybe it's because otherwise the inductive hypotheses will have all these additional equality hypotheses? Or maybe it could be done butinduction
would need to work out which of these generalized variables should be added to thegeneralizing
clause, and that hasn't been done yet?It looks like the difference in your examples is from
cases
not being efficient with its generalizations.
Does this mean any instance of cases
can be replaced by induction
?
Kyle Miller (Mar 19 2025 at 15:27):
Can you expand on what you mean? Because what I was saying is that cases
has an additional feature that induction
doesn't have, so you can't replace the token cases
with induction
and expect it to work.
Leni Aniva (Mar 20 2025 at 01:10):
Kyle Miller said:
Can you expand on what you mean? Because what I was saying is that
cases
has an additional feature thatinduction
doesn't have, so you can't replace the tokencases
withinduction
and expect it to work.
Is it possible to replace every single instance of cases
with induction
combined with revert
or generalize
?
Kyle Miller (Mar 20 2025 at 18:44):
Seems plausible. You might often need rename_i
as well.
Last updated: May 02 2025 at 03:31 UTC