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) := cdiscards 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) := cis elaborated intomatch 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-modelet).
Interesting. it appears to work in term-mode but not in do-notation.
Last updated: Feb 28 2026 at 14:05 UTC