Documentation

Init.Data.List.Zip

Lemmas about List.zip, List.zipWith, List.zipWithAll, and List.unzip. #

Zippers #

zipWith #

theorem List.zipWith_comm {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αβγ} {as : List α} {bs : List β} :
zipWith f as bs = zipWith (fun (b : β) (a : α) => f a b) bs as
theorem List.zipWith_comm_of_comm {α : Type u_1} {β : Type u_2} {f : ααβ} (comm : ∀ (x y : α), f x y = f y x) {l l' : List α} :
zipWith f l l' = zipWith f l' l
@[simp]
theorem List.zipWith_self {α : Type u_1} {δ : Type u_2} {f : ααδ} {l : List α} :
zipWith f l l = map (fun (a : α) => f a a) l
@[reducible, inline, deprecated List.zipWith_self (since := "2025-01-29")]
abbrev List.zipWith_same {α : Type u_1} {δ : Type u_2} {f : ααδ} {l : List α} :
zipWith f l l = map (fun (a : α) => f a a) l
Equations
theorem List.getElem?_zipWith {α : Type u_1} {β : Type u_2} {γ : Type u_3} {as : List α} {bs : List β} {f : αβγ} {i : Nat} :
(zipWith f as bs)[i]? = match as[i]?, bs[i]? with | some a, some b => some (f a b) | x, x_1 => none

See also getElem?_zipWith' for a variant using Option.map and Option.bind rather than a match.

theorem List.getElem?_zipWith' {α : Type u_1} {β : Type u_2} {γ : Type u_3} {l₁ : List α} {l₂ : List β} {f : αβγ} {i : Nat} :
(zipWith f l₁ l₂)[i]? = (Option.map f l₁[i]?).bind fun (g : βγ) => Option.map g l₂[i]?

Variant of getElem?_zipWith using Option.map and Option.bind rather than a match.

theorem List.getElem?_zipWith_eq_some {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αβγ} {l₁ : List α} {l₂ : List β} {z : γ} {i : Nat} :
(zipWith f l₁ l₂)[i]? = some z (x : α), (y : β), l₁[i]? = some x l₂[i]? = some y f x y = z
theorem List.getElem?_zip_eq_some {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} {z : α × β} {i : Nat} :
(l₁.zip l₂)[i]? = some z l₁[i]? = some z.fst l₂[i]? = some z.snd
theorem List.head?_zipWith {α : Type u_1} {β : Type u_2} {γ : Type u_3} {as : List α} {bs : List β} {f : αβγ} :
(zipWith f as bs).head? = match as.head?, bs.head? with | some a, some b => some (f a b) | x, x_1 => none
theorem List.head_zipWith {α : Type u_1} {β : Type u_2} {γ : Type u_3} {as : List α} {bs : List β} {f : αβγ} (h : zipWith f as bs []) :
(zipWith f as bs).head h = f (as.head ) (bs.head )
@[simp]
theorem List.zipWith_map {γ : Type u_1} {δ : Type u_2} {α : Type u_3} {β : Type u_4} {μ : Type u_5} {f : γδμ} {g : αγ} {h : βδ} {l₁ : List α} {l₂ : List β} :
zipWith f (map g l₁) (map h l₂) = zipWith (fun (a : α) (b : β) => f (g a) (h b)) l₁ l₂
theorem List.zipWith_map_left {α : Type u_1} {β : Type u_2} {α' : Type u_3} {γ : Type u_4} {l₁ : List α} {l₂ : List β} {f : αα'} {g : α'βγ} :
zipWith g (map f l₁) l₂ = zipWith (fun (a : α) (b : β) => g (f a) b) l₁ l₂
theorem List.zipWith_map_right {α : Type u_1} {β : Type u_2} {β' : Type u_3} {γ : Type u_4} {l₁ : List α} {l₂ : List β} {f : ββ'} {g : αβ'γ} :
zipWith g l₁ (map f l₂) = zipWith (fun (a : α) (b : β) => g a (f b)) l₁ l₂
theorem List.zipWith_foldr_eq_zip_foldr {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} {l₁ : List α} {l₂ : List β} {f : αβγ} {i : δ} {g : γδδ} :
foldr g i (zipWith f l₁ l₂) = foldr (fun (p : α × β) (r : δ) => g (f p.fst p.snd) r) i (l₁.zip l₂)
theorem List.zipWith_foldl_eq_zip_foldl {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} {l₁ : List α} {l₂ : List β} {f : αβγ} {i : δ} {g : δγδ} :
foldl g i (zipWith f l₁ l₂) = foldl (fun (r : δ) (p : α × β) => g r (f p.fst p.snd)) i (l₁.zip l₂)
@[simp]
theorem List.zipWith_eq_nil_iff {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αβγ} {l : List α} {l' : List β} :
zipWith f l l' = [] l = [] l' = []
theorem List.map_zipWith {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} {f : αβ} {g : γδα} {l : List γ} {l' : List δ} :
map f (zipWith g l l') = zipWith (fun (x : γ) (y : δ) => f (g x y)) l l'
theorem List.take_zipWith {α✝ : Type u_1} {α✝¹ : Type u_2} {α✝² : Type u_3} {f : α✝α✝¹α✝²} {l : List α✝} {l' : List α✝¹} {i : Nat} :
take i (zipWith f l l') = zipWith f (take i l) (take i l')
theorem List.drop_zipWith {α✝ : Type u_1} {α✝¹ : Type u_2} {α✝² : Type u_3} {f : α✝α✝¹α✝²} {l : List α✝} {l' : List α✝¹} {i : Nat} :
drop i (zipWith f l l') = zipWith f (drop i l) (drop i l')
@[simp]
theorem List.tail_zipWith {α✝ : Type u_1} {α✝¹ : Type u_2} {α✝² : Type u_3} {f : α✝α✝¹α✝²} {l : List α✝} {l' : List α✝¹} :
(zipWith f l l').tail = zipWith f l.tail l'.tail
theorem List.zipWith_append {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αβγ} {l₁ l₁' : List α} {l₂ l₂' : List β} (h : l₁.length = l₂.length) :
zipWith f (l₁ ++ l₁') (l₂ ++ l₂') = zipWith f l₁ l₂ ++ zipWith f l₁' l₂'
theorem List.zipWith_eq_cons_iff {α : Type u_1} {β : Type u_2} {γ : Type u_3} {g : γ} {l : List γ} {f : αβγ} {l₁ : List α} {l₂ : List β} :
zipWith f l₁ l₂ = g :: l (a : α), (l₁' : List α), (b : β), (l₂' : List β), l₁ = a :: l₁' l₂ = b :: l₂' g = f a b l = zipWith f l₁' l₂'
theorem List.zipWith_eq_append_iff {α : Type u_1} {β : Type u_2} {γ : Type u_3} {l₁' l₂' : List γ} {f : αβγ} {l₁ : List α} {l₂ : List β} :
zipWith f l₁ l₂ = l₁' ++ l₂' (ws : List α), (xs : List α), (ys : List β), (zs : List β), ws.length = ys.length l₁ = ws ++ xs l₂ = ys ++ zs l₁' = zipWith f ws ys l₂' = zipWith f xs zs
@[simp]
theorem List.zipWith_replicate' {α : Type u_1} {β : Type u_2} {α✝ : Type u_3} {f : αβα✝} {a : α} {b : β} {n : Nat} :
zipWith f (replicate n a) (replicate n b) = replicate n (f a b)

See also List.zipWith_replicate in Init.Data.List.TakeDrop for a generalization with different lengths.

theorem List.map_uncurry_zip_eq_zipWith {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αβγ} {l : List α} {l' : List β} :
map (Function.uncurry f) (l.zip l') = zipWith f l l'
theorem List.map_zip_eq_zipWith {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : α × βγ} {l : List α} {l' : List β} :
map f (l.zip l') = zipWith (Function.curry f) l l'

zip #

theorem List.zip_eq_zipWith {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} :
l₁.zip l₂ = zipWith Prod.mk l₁ l₂
theorem List.zip_map {α : Type u_1} {γ : Type u_2} {β : Type u_3} {δ : Type u_4} {f : αγ} {g : βδ} {l₁ : List α} {l₂ : List β} :
(map f l₁).zip (map g l₂) = map (Prod.map f g) (l₁.zip l₂)
theorem List.zip_map_left {α : Type u_1} {γ : Type u_2} {β : Type u_3} {f : αγ} {l₁ : List α} {l₂ : List β} :
(map f l₁).zip l₂ = map (Prod.map f id) (l₁.zip l₂)
theorem List.zip_map_right {β : Type u_1} {γ : Type u_2} {α : Type u_3} {f : βγ} {l₁ : List α} {l₂ : List β} :
l₁.zip (map f l₂) = map (Prod.map id f) (l₁.zip l₂)
@[simp]
theorem List.tail_zip {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} :
(l₁.zip l₂).tail = l₁.tail.zip l₂.tail
theorem List.zip_append {α : Type u_1} {β : Type u_2} {l₁ r₁ : List α} {l₂ r₂ : List β} (_h : l₁.length = l₂.length) :
(l₁ ++ r₁).zip (l₂ ++ r₂) = l₁.zip l₂ ++ r₁.zip r₂
theorem List.zip_map' {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αβ} {g : αγ} {l : List α} :
(map f l).zip (map g l) = map (fun (a : α) => (f a, g a)) l
theorem List.of_mem_zip {α : Type u_1} {β : Type u_2} {a : α} {b : β} {l₁ : List α} {l₂ : List β} :
(a, b) l₁.zip l₂a l₁ b l₂
theorem List.map_fst_zip {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} :
l₁.length l₂.lengthmap Prod.fst (l₁.zip l₂) = l₁
theorem List.map_snd_zip {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} :
l₂.length l₁.lengthmap Prod.snd (l₁.zip l₂) = l₂
theorem List.map_prod_left_eq_zip {α : Type u_1} {β : Type u_2} {l : List α} {f : αβ} :
map (fun (x : α) => (x, f x)) l = l.zip (map f l)
theorem List.map_prod_right_eq_zip {α : Type u_1} {β : Type u_2} {l : List α} {f : αβ} :
map (fun (x : α) => (f x, x)) l = (map f l).zip l
@[simp]
theorem List.zip_eq_nil_iff {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} :
l₁.zip l₂ = [] l₁ = [] l₂ = []
theorem List.zip_eq_cons_iff {α : Type u_1} {β : Type u_2} {a : α} {b : β} {l : List (α × β)} {l₁ : List α} {l₂ : List β} :
l₁.zip l₂ = (a, b) :: l (l₁' : List α), (l₂' : List β), l₁ = a :: l₁' l₂ = b :: l₂' l = l₁'.zip l₂'
theorem List.zip_eq_append_iff {α : Type u_1} {β : Type u_2} {l₁' l₂' : List (α × β)} {l₁ : List α} {l₂ : List β} :
l₁.zip l₂ = l₁' ++ l₂' (ws : List α), (xs : List α), (ys : List β), (zs : List β), ws.length = ys.length l₁ = ws ++ xs l₂ = ys ++ zs l₁' = ws.zip ys l₂' = xs.zip zs
@[simp]
theorem List.zip_replicate' {α : Type u_1} {β : Type u_2} {a : α} {b : β} {n : Nat} :

See also List.zip_replicate in Init.Data.List.TakeDrop for a generalization with different lengths.

zipWithAll #

theorem List.getElem?_zipWithAll {α : Type u_1} {β : Type u_2} {γ : Type u_3} {as : List α} {bs : List β} {f : Option αOption βγ} {i : Nat} :
(zipWithAll f as bs)[i]? = match as[i]?, bs[i]? with | none, none => none | a?, b? => some (f a? b?)
theorem List.head?_zipWithAll {α : Type u_1} {β : Type u_2} {γ : Type u_3} {as : List α} {bs : List β} {f : Option αOption βγ} :
(zipWithAll f as bs).head? = match as.head?, bs.head? with | none, none => none | a?, b? => some (f a? b?)
@[simp]
theorem List.head_zipWithAll {α : Type u_1} {β : Type u_2} {γ : Type u_3} {as : List α} {bs : List β} {f : Option αOption βγ} (h : zipWithAll f as bs []) :
(zipWithAll f as bs).head h = f as.head? bs.head?
@[simp]
theorem List.tail_zipWithAll {α : Type u_1} {β : Type u_2} {γ : Type u_3} {as : List α} {bs : List β} {f : Option αOption βγ} :
(zipWithAll f as bs).tail = zipWithAll f as.tail bs.tail
theorem List.zipWithAll_map {γ : Type u_1} {δ : Type u_2} {α : Type u_1} {β : Type u_2} {μ : Type u_3} {f : Option γOption δμ} {g : αγ} {h : βδ} {l₁ : List α} {l₂ : List β} :
zipWithAll f (map g l₁) (map h l₂) = zipWithAll (fun (a : Option α) (b : Option β) => f (g <$> a) (h <$> b)) l₁ l₂
theorem List.zipWithAll_map_left {α : Type u_1} {β : Type u_2} {α' : Type u_1} {γ : Type u_3} {l₁ : List α} {l₂ : List β} {f : αα'} {g : Option α'Option βγ} :
zipWithAll g (map f l₁) l₂ = zipWithAll (fun (a : Option α) (b : Option β) => g (f <$> a) b) l₁ l₂
theorem List.zipWithAll_map_right {α : Type u_1} {β β' : Type u_2} {γ : Type u_3} {l₁ : List α} {l₂ : List β} {f : ββ'} {g : Option αOption β'γ} :
zipWithAll g l₁ (map f l₂) = zipWithAll (fun (a : Option α) (b : Option β) => g a (f <$> b)) l₁ l₂
theorem List.map_zipWithAll {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} {f : αβ} {g : Option γOption δα} {l : List γ} {l' : List δ} :
map f (zipWithAll g l l') = zipWithAll (fun (x : Option γ) (y : Option δ) => f (g x y)) l l'
@[simp]
theorem List.zipWithAll_replicate {α : Type u_1} {β : Type u_2} {α✝ : Type u_3} {f : Option αOption βα✝} {a : α} {b : β} {n : Nat} :
zipWithAll f (replicate n a) (replicate n b) = replicate n (f (some a) (some b))

unzip #

@[simp]
theorem List.unzip_fst {α✝ : Type u_1} {β✝ : Type u_2} {l : List (α✝ × β✝)} :
@[simp]
theorem List.unzip_snd {α✝ : Type u_1} {β✝ : Type u_2} {l : List (α✝ × β✝)} :
theorem List.unzip_eq_map {α : Type u_1} {β : Type u_2} {l : List (α × β)} :
theorem List.zip_unzip {α : Type u_1} {β : Type u_2} (l : List (α × β)) :
theorem List.unzip_zip_left {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} :
l₁.length l₂.length(l₁.zip l₂).unzip.fst = l₁
theorem List.unzip_zip_right {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} :
l₂.length l₁.length(l₁.zip l₂).unzip.snd = l₂
theorem List.unzip_zip {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} (h : l₁.length = l₂.length) :
(l₁.zip l₂).unzip = (l₁, l₂)
theorem List.zip_of_prod {α : Type u_1} {β : Type u_2} {l : List α} {l' : List β} {xs : List (α × β)} (hl : map Prod.fst xs = l) (hr : map Prod.snd xs = l') :
xs = l.zip l'
theorem List.tail_zip_fst {α : Type u_1} {β : Type u_2} {l : List (α × β)} :
theorem List.tail_zip_snd {α : Type u_1} {β : Type u_2} {l : List (α × β)} :
@[simp]
theorem List.unzip_replicate {α : Type u_1} {β : Type u_2} {n : Nat} {a : α} {b : β} :