Zulip Chat Archive

Stream: new members

Topic: How to prove a match is exhaustive (or similar)


Ryan Greenblatt (Nov 18 2021 at 02:53):

I want to be able to use a proposition to show that a match case is impossible.
Something like:

def non_empty_list := {l : list  // l  []}

def extract_first (l : non_empty_list) :  :=
match l.val with
| [] := sorry -- prove impossible
| a::_ := a
end

Anyone know how to do this?

Kyle Miller (Nov 18 2021 at 02:57):

If you match on l.val, Lean won't specialize h.property to the different cases.

You can match on l itself:

def extract_first (l : non_empty_list) :  :=
match l with
| ⟨[], h := (h rfl).elim
| a::_, h := a
end

I'm using the angle bracket notation, which can be used for any inductive type with only one constructor (like subtype).

Kyle Miller (Nov 18 2021 at 02:58):

This is also a place where you can merge the match into the def syntax:

def extract_first : non_empty_list  
| ⟨[], h := (h rfl).elim
| a::_, h := a

Kyle Miller (Nov 18 2021 at 03:04):

(This actually has some consequences to how Lean generates the "equation lemmas". When you fold in the match syntax, you get

extract_first.equations._eqn_1 :  (h : list.nil  list.nil), extract_first list.nil , h = _.elim
extract_first.equations._eqn_2 :  (a : ) (_x : list ) (h : a :: _x  list.nil), extract_first a :: _x, h = a

but if you keep the match separate you get

extract_first.equations._eqn_1 :  (l : non_empty_list), extract_first l = extract_first._match_1 l
extract_first._match_1.equations._eqn_1 :  (h : list.nil  list.nil), extract_first._match_1 list.nil , h = _.elim
extract_first._match_1.equations._eqn_2 :  (a : ) (_x : list ) (h : a :: _x  list.nil), extract_first._match_1 a :: _x, h = a

As I understand it, the difference is in what happens when you unfold definitions in a proof. The second one will unfold into extract_first._match_1, but if you unfold this, too, they're otherwise identical.)


Last updated: Dec 20 2023 at 11:08 UTC