Zulip Chat Archive
Stream: lean4
Topic: proving list nonempty by pattern match
James Sully (Dec 03 2023 at 01:39):
if I have list : List Int
, and
match list with
| [] => ...
| List.cons _ _ => ...
What's the syntax for obtaining a proof of list ≠ []
in the second branch?
Shreyas Srinivas (Dec 03 2023 at 01:57):
match h : list with
| [] => ...
| List.cons _ _ => ...
Shreyas Srinivas (Dec 03 2023 at 02:01):
You should have the hypothesis h : list = List.cons ....
. inside the cons arm. Then you can introduce a local have
declaration in the cons arm. With a little bit of simp
on h, you should be able to get the proof of list ≠ []
James Sully (Dec 03 2023 at 02:04):
neat it works, thank you! I'm trying to understand what this means... h
is given the type of the value of the list?? Where can I read about what's going on here?
Shreyas Srinivas (Dec 03 2023 at 02:06):
I am not sure there is a deeper explanation. Every inductive type comes with a casesOn
recursor. This is produced by lean along with rec
.
Shreyas Srinivas (Dec 03 2023 at 02:06):
If I remember this correctly, match uses the cases recursor.
James Sully (Dec 03 2023 at 02:07):
I will read through this chapter: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html
Shreyas Srinivas (Dec 03 2023 at 02:08):
If you are referring to the name h
, its type is a value of Prop
. It is an equality.
James Sully (Dec 03 2023 at 02:09):
h for hypothesis?
Shreyas Srinivas (Dec 03 2023 at 02:09):
h
is a name I picked. You can give it whatever name you like
James Sully (Dec 03 2023 at 02:09):
sure, I'm asking about the convention
Shreyas Srinivas (Dec 03 2023 at 02:10):
James Sully said:
h for hypothesis?
That's my best guess. I have never bothered to ask (maybe I should have).
Kyle Miller (Dec 03 2023 at 02:10):
James Sully said:
h is given the type of the value of the list??
h
is given a proof that list
equals the given pattern for the given match arm
Kyle Miller (Dec 03 2023 at 02:10):
(and yeah, I think h
is "hypothesis". it's often used as a prefix for proof variables, like hpos : 0 < x
for the fact that x
is positive)
James Sully (Dec 03 2023 at 02:10):
ah, I see
James Sully (Dec 03 2023 at 02:11):
thanks both!
Kyle Miller (Dec 03 2023 at 02:15):
This notation by the way appears in a few other constructs, like if h : x = 0 then ... else ...
, which gives you h : x = 0
in the true case and x : Not (x = 0)
in the false case, or for h : x in lst do ...
to get a proof that x
is in lst
in the loop body.
James Sully (Dec 03 2023 at 02:17):
Oh nice, that's good to know.
James Sully (Dec 03 2023 at 02:17):
Would the by simp [h]
bottom out in a List.noConfusion
?
James Sully (Dec 03 2023 at 02:18):
if written out explicitly?
Kyle Miller (Dec 03 2023 at 02:20):
I assume you mean if you have something like have : list ≠ [] := by simp [h]
in the second branch? Yeah, that sounds right.
James Sully (Dec 03 2023 at 02:20):
yep. ok cool
Kyle Miller (Dec 03 2023 at 02:21):
You could also do by intro h'; cases h.symm.trans h'
(untested!), which would also use List.noConfusion
. The h.symm.trans h'
should be something :: something = []
James Sully (Dec 03 2023 at 02:25):
that also works. I'm not familiar with the cases
tactic yet, I've only used cases'
from the Lean Game Server, which I think is a simplified version
Kyle Miller (Dec 03 2023 at 02:26):
cases'
is like cases
but it has different syntax for how you name hypotheses (it's the Lean 3 style cases
tactic)
James Sully (Dec 03 2023 at 02:27):
Oh is the h.symm.trans
just function application? Like trans (symm h)
Kyle Miller (Dec 03 2023 at 02:28):
It takes a bit of a leap into dependent type theory to see why cases
on an equality makes sense, but all you need to know is that it tries to make both sides of an equality exactly the same. That might mean substituting variables automatically, or, in this case, realizing we're in an impossible situation and close the goal using List.noConfusion
.
Kyle Miller (Dec 03 2023 at 02:28):
Oh, yeah, h.symm.trans h'
is Eq.trans (Eq.symm h) h'
.
James Sully (Dec 03 2023 at 02:34):
what's the type of h.symm.trans
?
James Sully (Dec 03 2023 at 02:35):
i'm trying to extract it into a have
to understand better
James Sully (Dec 03 2023 at 02:41):
If i'm understanding right:
h.symm : x :: xs = list
h.symm.trans : (list = c) -> x :: xs = c
James Sully (Dec 03 2023 at 02:46):
I wrote it out in excruciating detail and I'm starting to understand haha
match h : digits with
| [] => none
| x :: xs =>
have digits_ne_nil : digits ≠ [] := by
-- simp [h]
-- or
-- rw [h]
-- exact λ h2 => List.noConfusion h2
-- or
intro (h1 : digits = [])
have h2 {c} : (digits = c) → x :: xs = c := h.symm.trans
have h3 : x :: xs = [] := h2 h1
cases h3
Last updated: Dec 20 2023 at 11:08 UTC