Zulip Chat Archive
Stream: lean4
Topic: Extra argument from `cases` tactic
Leni Aniva (Jan 17 2024 at 06:55):
The Or.casesOn
function takes 6
arguments:
#check Or.casesOn
Or.casesOn {a b : Prop} {motive : a ∨ b → Prop} (t : a ∨ b) (inl : ∀ (h : a), motive (_ : a ∨ b))
(inr : ∀ (h : b), motive (_ : a ∨ b)) : motive t
namely a b motive t inl inr
.
Consider the following proof of the commutativity of Or
:
theorem or_comm: ∀ (p q: Prop), p ∨ q → q ∨ p := by
intro p q h
cases h; rename_i a
apply Or.inr
assumption
apply Or.inl
assumption
Printing out the value of or_comm
shows that despite having two motives, there is an extra argument (Eq.refl h)
being applied to the result of Or.casesOn
:
fun p q h =>
Or.casesOn (motive := fun t => h = t → q ∨ p) h (fun h_1 h_2 => Eq.symm h_2 ▸ Or.inr h_1)
(fun h_1 h_2 => Eq.symm h_2 ▸ Or.inl h_1) (Eq.refl h)
Why does the cases
tactic generate this extraneous Eq.refl h
and why could it not be bundled into the inl
and inr
motives?
Ruben Van de Velde (Jan 17 2024 at 07:00):
I think you should generally not read too much into the exact terms generated by a tactic
Joachim Breitner (Jan 17 2024 at 08:28):
Why does the cases tactic generate this extraneous Eq.refl h and why could it not be bundled into the inl and inr motives?
This is an extra assumption where it keeps track of the relation between the original value (h
) and the concrete value in the branch (inl a
resp. inl b
). Since these are props it’s not so useful and it hides them from you, but if you case split on value you sometimes care a lot about that equality. It’s what you get when you write match h : x with …
.
Leni Aniva (Jan 17 2024 at 21:19):
Joachim Breitner said:
Why does the cases tactic generate this extraneous Eq.refl h and why could it not be bundled into the inl and inr motives?
This is an extra assumption where it keeps track of the relation between the original value (
h
) and the concrete value in the branch (inl a
resp.inl b
). Since these are props it’s not so useful and it hides them from you, but if you case split on value you sometimes care a lot about that equality. It’s what you get when you writematch h : x with …
.
is there a case where this would be visible? Why not bundle the Eq.refl
term into the two branches of the motives? For example maybe we could have
fun p q h =>
Or.casesOn (motive := fun t => h = t → q ∨ p) h (fun h_1 => Eq.symm (Eq.refl h) ▸ Or.inr h_1)
(fun h_1 => Eq.symm (Eq.refl h) ▸ Or.inl h_1)
Leni Aniva (Jan 17 2024 at 22:11):
I found this in the documentation of CasesOn.lean
and this seems to be related to the remaining term?
/--
Given a `casesOn` application `c` of the form
```
casesOn As (fun is x => motive[i, xs]) is major (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining
```
and an expression `e : B[is, major]`, construct the term
```
casesOn As (fun is x => B[is, x] → motive[i, xs]) is major (fun ys_1 (y : B[C_1[ys_1]]) => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n (y : B[C_n[ys_n]]) => (alt_n : motive (C_n[ys_n]) e remaining
```
We use `kabstract` to abstract the `is` and `major` from `B[is, major]`.
-/
def CasesOnApp.addArg (c : CasesOnApp) (arg : Expr) (checkIfRefined : Bool := false) : MetaM CasesOnApp := do
Joachim Breitner (Jan 18 2024 at 09:29):
Does that typecheck? are you pondering a different type signature for casesOn
here?
Probably it’s possible to hard-code that feature (providing that equality in the branches) in the casesOn
eliminator, but if it can be done using a suitable motive
instantiation by the tactic, then that’s more flexible, isn't it?
Leni Aniva (Jan 18 2024 at 19:25):
Joachim Breitner said:
Does that typecheck? are you pondering a different type signature for
casesOn
here?Probably it’s possible to hard-code that feature (providing that equality in the branches) in the
casesOn
eliminator, but if it can be done using a suitablemotive
instantiation by the tactic, then that’s more flexible, isn't it?
I think the motive would have to be changed
Last updated: May 02 2025 at 03:31 UTC