Zulip Chat Archive

Stream: lean4

Topic: How to eliminate dependent pattern matchings?


Ryan Lahfa (Jun 20 2024 at 11:59):

Given the following example:

inductive Tree (T: Type) where
| none : Tree T
| some : T  Tree T  Tree T  Tree T

#reduce Tree.some (Tree.none) (Tree.none)

def height (t: Tree T): Nat := match t with
| .none => 0
| .some _ left right => 1 + max (height left) (height right)

structure WeirdT {T U: Type} where
  left: Tree T
  right: Tree T
  c: Nat
  x: height left + height right = c
  y: Nat

def weird_fun {U: Type} (t: Tree T): Tree (@WeirdT T U) :=
  match t with
  | .none => Tree.none
  | .some _ left right => match Hbf : (height left) + (height right) with
    | 1 => Tree.some (WeirdT.mk _ _ _ Hbf 0) .none .none
    | 2 => Tree.some (WeirdT.mk _ _ _ Hbf 1) .none .none
    | 3 => Tree.some (WeirdT.mk _ _ _ Hbf 2) .none .none
    | 4 => Tree.some (WeirdT.mk _ _ _ Hbf 3) .none .none
    | _ => Tree.none

example {left right: Tree T} (Hbf: height left + height right = 0): Tree.some (WeirdT.mk left right 0 Hbf 0) t u = weird_fun (Tree.some n (Tree.none) (Tree.none)) := by
  simp [weird_fun]
  -- Here, `split` can be used, but is there a way to eliminate directly the right branch?

I know that split + rename_i / case can be used to go through a dependent pattern matching, but in my code, I have multiple nested dependent pattern matchings and split makes the proof much more verbose (slower?).

Am I missing a trick here?

Markus Himmel (Jun 20 2024 at 12:03):

simp and dsimp are aware of match, so you can make progress with dsimp [height] in your case. Is that what you're looking for?

Damiano Testa (Jun 20 2024 at 12:04):

Or simply using

@[simp] def height (t: Tree T): Nat := match t with

Ryan Lahfa (Jun 20 2024 at 13:00):

@Markus Himmel Not really, because in my non-MWE, all that's doing is just unfolding a mutually recursive definition and I'm not sure this creates progress, but I see why this MWE makes it appear as the solution.

Ryan Lahfa (Jun 20 2024 at 13:07):

Here's an updated MWE where dsimp/simp doesn't seem to work to me:

inductive Tree (T: Type) where
| mk : T  Option (Tree T)  Option (Tree T)  Tree T

#reduce Tree.mk (Option.none) (Option.none)

mutual
def height (t: Option (Tree T)): Nat := match t with
| .none => 0
| .some t => height_node t
def height_node (t: Tree T): Nat := match t with
| .mk _ left right => 1 + max (height left) (height right)
end

structure WeirdT {T U: Type} where
  left: Option (Tree T)
  right: Option (Tree T)
  c: Nat
  x: height left + height right = c
  y: Nat

def weird_fun {U: Type} (t: Option (Tree T)): Option (Tree (@WeirdT T U)) :=
  match t with
  | .none => Option.none
  | .some (Tree.mk _ left right) => match Hbf : (height left) + (height right) with
    | 1 => .some $ Tree.mk (WeirdT.mk _ _ _ Hbf 0) .none .none
    | 2 => .some $ Tree.mk (WeirdT.mk _ _ _ Hbf 1) .none .none
    | 3 => .some $ Tree.mk (WeirdT.mk _ _ _ Hbf 2) .none .none
    | 4 => .some $ Tree.mk (WeirdT.mk _ _ _ Hbf 3) .none .none
    | _ => Option.none

example {left right: Option (Tree T)} (Hbf: height left + height right = 1): Option.some (Tree.mk (WeirdT.mk left right 1 Hbf 0) t u) = weird_fun (.some $ .mk n left right) := by
  simp [weird_fun]
  dsimp [height] -- shows a mutual defn
  simp [height] -- makes no progress
  simp [Hbf]

Jakob von Raumer (Jun 20 2024 at 14:06):

Try split

Ryan Lahfa (Jun 20 2024 at 14:34):

Jakob von Raumer said:

Try split

Yes but this is what I want to avoid :P


Last updated: May 02 2025 at 03:31 UTC