Zulip Chat Archive
Stream: general
Topic: Combining `intro` and `cases`
Mai (Jan 29 2026 at 15:43):
Is there a way to combine the intro and cases tactics? for example, here:
inductive Any
opaque Any.level : Any -> Nat := nofun
structure Ctx (level : Nat) where
vars : List Any
var_level_le_level : ∀ v ∈ vars, v.level <= level
def Ctx.with (Γ : Ctx level) (var : Any) {var_level : var.level = level + 1} : Ctx (level + 1) :=
{ Γ with
vars := var :: Γ.vars
var_level_le_level v := by
intro hv
cases hv
case head => simp [var_level]
case tail mem =>
apply Nat.le_add_right_of_le
exact Γ.var_level_le_level v mem }
Damiano Testa (Jan 29 2026 at 15:45):
You can probably use the rintro tactic and then do the desctructuring there.
Robin Arnez (Jan 29 2026 at 16:12):
That is,
inductive Any
opaque Any.level : Any -> Nat := nofun
structure Ctx (level : Nat) where
vars : List Any
var_level_le_level : ∀ v ∈ vars, v.level <= level
def Ctx.with (Γ : Ctx level) (var : Any) {var_level : var.level = level + 1} : Ctx (level + 1) :=
{ Γ with
vars := var :: Γ.vars
var_level_le_level v := by
rintro (_ | ⟨_, mem⟩)
· simp [var_level]
· apply Nat.le_add_right_of_le
exact Γ.var_level_le_level v mem }
Mai (Jan 29 2026 at 16:19):
That's pretty neat. what do the underscores represent?
Robin Arnez (Jan 29 2026 at 16:48):
Placeholders? Just like in match
Mai (Jan 30 2026 at 11:08):
@Robin Arnez I mean, they aren't present in my cases version. What information do they represent
Robin Arnez (Jan 30 2026 at 13:08):
Well the second underscore is basically the same as in
cases hv
case head => ...
case tail _ mem => ...
i.e. don't assign a variable name. The first underscore here is a placeholder for the constructor application of List.Mem.head, which doesn't bind any variables, so you could also write ⟨⟩ instead of the first _.
Last updated: Feb 28 2026 at 14:05 UTC