Zulip Chat Archive
Stream: lean4
Topic: working with `filterMap` and `attach`
Logan Murphy (Jun 19 2024 at 19:54):
I have some non-structurally recursive code, and eventually I use a function looking like this:
def myMapFn
{α β : Type}
(l : List α)
(f : {x // x ∈ l} → β)
(P : β → Bool) : List β :=
l.attach |> List.filterMap (fun x ↦ if P (f x) then f x else none)
Now, I feel like I should be able to prove something akin to the following :
theorem aux {α : Type} {h : α} {t : List α} : h ∈ h::t := (List.mem_cons_self h t)
theorem aux' {α : Type} {h : α} {t : List α} (x : { x // x ∈ t }) : ↑x ∈ h :: t := by apply List.mem_cons_of_mem ; apply x.property
theorem attach_map_cons_pos
{α β : Type}
(h : α)
(t : List α)
(f : {x // x ∈ h::t} → β)
(P : β → Bool)
(h': P (f ⟨h, aux⟩)) :
myMapFn (h::t) f P =
f ⟨h,aux⟩ :: myMapFn t (λ x => f ⟨x, aux' x⟩) P :=
proving this gets a little messy, but I'm able to reduce it to the following goal :
α β : Type
h : α
t : List α
f : { x // x ∈ h :: t } → β
P : β → Bool
h' : P (f ⟨h, aux⟩) = true
x tail : List { x // x ∈ h :: t }
val : α
property : val ∈ h :: t
heq : (h :: t).attach = ⟨val, property⟩ :: tail
x_1 : Option β
left : P (f ⟨val, property⟩) = true
⊢ List.filterMap (fun x ↦ if P (f x) = true then some (f x) else none) tail =
List.filterMap (fun x ↦ if P (f ⟨↑x, aux' x⟩) = true then some (f ⟨↑x, aux' x⟩) else none) t.attach
but I seem to be stuck here. Am I barking up the wrong tree? Is this even provable?
Floris van Doorn (Jun 19 2024 at 21:01):
This was definitely more painful than it should be. I was missing lemmas like attach_cons
, so I unfolded stuff, but then I was still missing lemmas.
import Mathlib.Data.List.Basic
open List
def myMapFn
{α β : Type}
(l : List α)
(f : {x // x ∈ l} → β)
(P : β → Bool) : List β :=
l.attach |> List.filterMap (fun x ↦ if P (f x) then f x else none)
theorem aux {α : Type} {h : α} {t : List α} : h ∈ h::t := (List.mem_cons_self h t)
theorem aux' {α : Type} {h : α} {t : List α} (x : { x // x ∈ t }) : ↑x ∈ h :: t := by
apply List.mem_cons_of_mem ; apply x.property
theorem filterMap_id_map {α β} (f : α → Option β) (l : List α) :
filterMap id (map f l) = filterMap f l :=
filterMap_map ..
theorem attach_map_cons_pos
{α β : Type}
(h : α)
(t : List α)
(f : {x // x ∈ h::t} → β)
(P : β → Bool)
(h': P (f ⟨h, aux⟩)) :
myMapFn (h::t) f P =
f ⟨h,aux⟩ :: myMapFn t (λ x => f ⟨x, aux' x⟩) P := by
simp_rw [myMapFn, attach, attachWith, pmap, filterMap_cons, h']
simp (config := {singlePass := true}) only [← filterMap_id_map]
simp_rw [map_pmap]
congr 2
exact pmap_congr t fun a _ h₁ => congrFun rfl
Logan Murphy (Jun 19 2024 at 21:03):
Brilliant! Thanks a ton Floris
Last updated: May 02 2025 at 03:31 UTC