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