In Lean4, I am stuck in a proof with a goal like this:
⊢ (match
match a :: b with
| [] => []
| [x] => [x]
| x :: xs => x :: [delim] :: intersperse [delim] xs with
| [] => []
| a :: as => a ++ join as) =
delim :: tail
Intuitively to me I would prove this by doing a case-by case analysis of the inner match statement. In other words, I would expect some tactic that would generate three subgoals:
- Add
a :: b = []
as an additional hypothesis, goal of
⊢ (match []
| [] => []
| a :: as => a ++ join as) =
delim :: tail
- Add
a :: b = [x]
as an additional hypothesis, goal of
⊢ (match [x]
| [] => []
| a :: as => a ++ join as) =
delim :: tail
- Add
a :: b = x :: xs
as an additional hypothesis$,^\dagger$ goal of
⊢ (match x :: [delim] :: intersperse [delim] xs
| [] => []
| a :: as => a ++ join as) =
delim :: tail
Here's a list of some things I have tried to solve this.
- The
split
tactic seems to split the outer match rather than the inner match, and it doesn't name any of the hypotheses, which makes it impossible to continue the proof. I can't seem to figure out any way to modify this behavior. - Using the
cases
tactic on the expression being matched:cases h₂: a::b with | nil => ... | cons a b | => ...
. This does successfully do a case split based on the value of the match expression, but it splits it into thenil
andcons
cases, rather than the three arms of the match. - I attempted to construct a toy problem to experiment with:
theorem foo (a:α) (b:List α) (P: b ≠ []): (match a :: b with | [] => [] | [x] => [x] | x :: xs => c) = c
. I thought that this theorem would require a case by case analysis, but it turns outsimp
just solved it! When I look atsimp?
's output, it saysTry this: simp only [split_match.match_1.eq_3]
, but the theoremsplit_match.match_1.eq_3
doesn't seem to actually exist if I try to use it:
invalid field notation, type is not of the form (C ...) where C is a constant
split_match.match_1
has type
(motive : List ?m.36429 → Sort ?u.36427) →
(x : List ?m.36429) →
(Unit → motive []) →
((x : ?m.36429) → motive [x]) → ((x : ?m.36429) → (xs : List ?m.36429) → motive (x :: xs)) → motive x
$\dagger$ I think this hypothesis could be even stronger because we know it didn't match the second case, but I'm not worried about that.