Zulip Chat Archive

Stream: general

Topic: Proving fact about the result of List.partition


Mai (Jan 26 2026 at 11:08):

Hi, I am pretty much a newbie so forgive me if this is obvious. How would I go about proving this?

      let (dom, rest) := pres.partition (Eq x  Prod.fst)
      let proof :  y  dom, y.fst = x := by
        intros y hy
        sorry

Aaron Liu (Jan 26 2026 at 11:13):

this one isn't provable, because let (a, b) := c discards the information that (a, b) = c

Jakub Nowak (Jan 26 2026 at 11:13):

It's hard to help you, I would have to spend additional time guessing what are the types of variables etc. Try to make it into #mwe with the goal you want to prove and sorry to fill.

Mai (Jan 26 2026 at 11:23):

I apologize. here's a working example

example (pres : List (Nat × a)) (x : Nat) : { dom : List (Nat × a) //  y  dom, y.fst = x } :=
  let (dom, rest) := pres.partition (Eq x  Prod.fst)
  let proof :  y  dom, y.fst = x := by
    intros y hy
    sorry
  dom, proof

Mai (Jan 26 2026 at 11:26):

Aaron Liu said:

this one isn't provable, because let (a, b) := c discards the information that (a, b) = c

How can I get around this?

Aaron Liu (Jan 26 2026 at 11:27):

example (pres : List (Nat × a)) (x : Nat) : { dom : List (Nat × a) //  y  dom, y.fst = x } :=
  let part := pres.partition (Eq x  Prod.fst)
  let dom := part.fst
  let rest := part.snd
  let proof :  y  dom, y.fst = x := by
    intros y hy
    sorry
  dom, proof

Aaron Liu (Jan 26 2026 at 11:29):

or in this case you only need the first half so you can use docs#List.filter

Mai (Jan 26 2026 at 11:30):

oh. that seems silly

Mai (Jan 26 2026 at 11:30):

Why does it behave like this

Aaron Liu (Jan 26 2026 at 11:31):

since let (a, b) := c is elaborated into match c with | (a, b) => ...

Aaron Liu (Jan 26 2026 at 11:32):

so it loses the equation

Aaron Liu (Jan 26 2026 at 11:32):

but let a := c is just let a := c

Aaron Liu (Jan 26 2026 at 11:32):

the a gets added as a let-decl which retains its value

Mai (Jan 26 2026 at 11:33):

Aaron Liu said:

since let (a, b) := c is elaborated into match c with | (a, b) => ...

Why does it lose the equation? shouldn't the pattern be equal to c inside the branch?

Aaron Liu (Jan 26 2026 at 11:35):

no it isn't

Aaron Liu (Jan 26 2026 at 11:35):

since that isn't always possible to get definitionally

Aaron Liu (Jan 26 2026 at 11:36):

it has to be a propositional equality

Aaron Liu (Jan 26 2026 at 11:36):

which you can get with match hc : c with | (a, b) => ...

Aaron Liu (Jan 26 2026 at 11:36):

or with any other patterns too

Anne Baanen (Jan 26 2026 at 12:43):

There is another syntax for let that gives you access to the equation:

example (pres : List (Nat × a)) (x : Nat) : { dom : List (Nat × a) //  y  dom, y.fst = x } :=
  let (eq := h) (dom, rest) := pres.partition (Eq x  Prod.fst)
  -- h : List.partition ((fun b => decide (x = b)) ∘ Prod.fst) pres = (dom, rest)
  let proof :  y  dom, y.fst = x := by
    intros y hy
    grind
  dom, proof

I'm using grind here as a "cheat code" to close the proof, but if you want to practice you can try to do the proof manually :)

Anne Baanen (Jan 26 2026 at 12:44):

let (eq := ...) works in tactic mode and term mode (but I don't think this is documented anywhere for term-mode let).

Mai (Jan 28 2026 at 16:51):

Anne Baanen said:

let (eq := ...) works in tactic mode and term mode (but I don't think this is documented anywhere for term-mode let).

Interesting. it appears to work in term-mode but not in do-notation.


Last updated: Feb 28 2026 at 14:05 UTC