Compare commits

...

1 Commits

Author SHA1 Message Date
Kim Morrison
64c736ac2c feat: add foldl_flatMap and foldr_flatMap theorems
Add theorems relating folding over flatMapped collections to nested folds
for List, Array, and Vector. These theorems enable simplifying complex fold
operations by showing that (l.flatMap f).foldl g init equals
l.foldl (fun acc x => (f x).foldl g acc) init, and similarly for foldr.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 23:50:11 +01:00
3 changed files with 38 additions and 0 deletions

View File

@@ -3325,6 +3325,16 @@ theorem foldr_filterMap {f : α → Option β} {g : β → γγ} {xs : Arra
(xs.filterMap f).foldr g init = xs.foldr (fun x y => match f x with | some b => g b y | none => y) init := by
simp [foldr_filterMap']
theorem foldl_flatMap {f : α Array β} {g : γ β γ} {xs : Array α} {init : γ} :
(xs.flatMap f).foldl g init = xs.foldl (fun acc x => (f x).foldl g acc) init := by
rcases xs with l
simp [List.foldl_flatMap]
theorem foldr_flatMap {f : α Array β} {g : β γ γ} {xs : Array α} {init : γ} :
(xs.flatMap f).foldr g init = xs.foldr (fun x acc => (f x).foldr g acc) init := by
rcases xs with l
simp [List.foldr_flatMap]
theorem foldl_map_hom' {g : α β} {f : α α α} {f' : β β β} {a : α} {xs : Array α}
{stop : Nat} (h : x y, f' (g x) (g y) = g (f x y)) (w : stop = xs.size) :
(xs.map g).foldl f' (g a) 0 stop = g (xs.foldl f a) := by

View File

@@ -2632,6 +2632,22 @@ theorem foldr_map_hom {g : α → β} {f : ααα} {f' : β → β →
@[simp, grind _=_] theorem foldr_append {f : α β β} {b : β} {l l' : List α} :
(l ++ l').foldr f b = l.foldr f (l'.foldr f b) := by simp [foldr_eq_foldrM, -foldrM_pure]
theorem foldl_flatMap {f : α List β} {g : γ β γ} {l : List α} {init : γ} :
(l.flatMap f).foldl g init = l.foldl (fun acc x => (f x).foldl g acc) init := by
induction l generalizing init
· simp
next a l ih =>
simp only [flatMap_cons, foldl_cons]
rw [foldl_append, ih]
theorem foldr_flatMap {f : α List β} {g : β γ γ} {l : List α} {init : γ} :
(l.flatMap f).foldr g init = l.foldr (fun x acc => (f x).foldr g acc) init := by
induction l generalizing init
· simp
next a l ih =>
simp only [flatMap_cons, foldr_cons]
rw [foldr_append, ih]
@[grind =] theorem foldl_flatten {f : β α β} {b : β} {L : List (List α)} :
(flatten L).foldl f b = L.foldl (fun b l => l.foldl f b) b := by
induction L generalizing b <;> simp_all

View File

@@ -2378,6 +2378,18 @@ theorem foldr_filterMap {f : α → Option β} {g : β → γγ} {xs : Vect
cases xs; simp [Array.foldr_filterMap']
rfl
theorem foldl_flatMap {f : α Vector β m} {g : γ β γ} {xs : Vector α n} {init : γ} :
(xs.flatMap f).foldl g init = xs.foldl (fun acc x => (f x).foldl g acc) init := by
rcases xs with xs, rfl
simp only [foldl, flatMap]
rw [Array.foldl_flatMap]
theorem foldr_flatMap {f : α Vector β m} {g : β γ γ} {xs : Vector α n} {init : γ} :
(xs.flatMap f).foldr g init = xs.foldr (fun x acc => (f x).foldr g acc) init := by
rcases xs with xs, rfl
simp only [foldr, flatMap]
rw [Array.foldr_flatMap]
theorem foldl_map_hom {g : α β} {f : α α α} {f' : β β β} {a : α} {xs : Vector α n}
(h : x y, f' (g x) (g y) = g (f x y)) :
(xs.map g).foldl f' (g a) = g (xs.foldl f a) := by