Documentation

Cedar.Thm.Data.List.Lemmas

Properties of Lists #

This file contains useful lemmas about standard list functions and our custom variations on these.

any #

theorem List.any_of_mem {α : Type u_1} {f : αBool} {x : α} {xs : List α} (h₁ : x xs) (h₂ : f x = true) :
xs.any f = true

all #

theorem List.all_pmap_subtype {α : Type u_1} {p : αProp} (f : αBool) (as : List α) (h : ∀ (a : α), a asp a) :
((pmap Subtype.mk as h).all fun (x : { a : α // p a }) => f x.val) = as.all f

Copied from Mathlib. We can delete this if it gets added to Batteries.

map, map₁, map₂, map₃, and attach variants #

theorem List.map_congr {α : Type u_1} {β : Type u_2} {f g : αβ} {l : List α} :
(∀ (x : α), x lf x = g x)map f l = map g l

Copied from Mathlib. We can delete this if it gets added to Batteries.

theorem List.map_eq_doubleton {α : Type u_1} {β : Type u_2} {f : αβ} {xs : List α} {y₁ y₂ : β} :
map f xs = [y₁, y₂] (x₁ : α), (x₂ : α), xs = [x₁, x₂]

Similar to the standard library's map_eq_singleton_iff, but for doubleton.

We could probably make this an iff but currently don't need to.

theorem List.map_pmap_subtype {α : Type u_1} {β : Type u_2} {p : αProp} (f : αβ) (as : List α) (h : ∀ (a : α), a asp a) :
map (fun (x : { a : α // p a }) => f x.val) (pmap Subtype.mk as h) = map f as

Copied from Mathlib. We can delete this if it gets added to Batteries.

theorem List.map_pmap_subtype_snd {α : Type u_1} {β : Type u_2} {γ : Type u_3} {p : α × βProp} (f : βγ) (xs : List (α × β)) (h : ∀ (pair : α × β), pair xsp pair) :
map (fun (x : { pair : α × β // p pair }) => (x.val.fst, f x.val.snd)) (pmap Subtype.mk xs h) = map (fun (pair : α × β) => (pair.fst, f pair.snd)) xs

Not actually a special case of map_pmap_subtype -- you can use this in places you can't use map_pmap_subtype because the LHS function (being mapped) doesn't fit the map_pmap_subtype form but does fit this form (where the application of f is not the outermost AST node of the function, basically)

theorem List.attach_def {α : Type u_1} {as : List α} :
theorem List.mem_attach₂ {α : Type u_1} {β : Type u_2} [SizeOf α] [SizeOf β] {as : List (α × β)} {pair : { x : α × β // sizeOf x.snd < 1 + sizeOf as }} :
pair as.attach₂(pair.val.fst, pair.val.snd) as
@[simp]
theorem List.all_attach₂ {α : Type u_1} {β : Type u_2} [SizeOf α] [SizeOf β] {as : List (α × β)} {f : α × βBool} :
(as.attach₂.all fun (x : { x : α × β // sizeOf x.snd < 1 + sizeOf as }) => match x with | pair, property => f pair) = as.all f
@[simp]
theorem List.all_attach₂_snd {α : Type u_1} {β : Type u_2} [SizeOf α] [SizeOf β] {as : List (α × β)} {f : βBool} :
(as.attach₂.all fun (x : { x : α × β // sizeOf x.snd < 1 + sizeOf as }) => match x with | (fst, b), property => f b) = as.all fun (x : α × β) => match x with | (fst, b) => f b
theorem List.map₁_eq_map {α : Type u_1} {β : Type u_2} (f : αβ) (as : List α) :
(as.map₁ fun (x : { x : α // x as }) => f x.val) = map f as
theorem List.map₂_eq_map {γ : Type u_1} {α : Type u} {β : Type v} [SizeOf α] [SizeOf β] {xs : List (α × β)} (f : α × βγ) :
(xs.map₂ fun (x : { x : α × β // sizeOf x.snd < 1 + sizeOf xs }) => f x.val) = map f xs
theorem List.map₃_eq_map {γ : Type u_1} {α : Type u} {β : Type v} [SizeOf α] [SizeOf β] {xs : List (α × β)} (f : α × βγ) :
(xs.map₃ fun (x : { x : α × β // sizeOf x.snd < 1 + (1 + sizeOf xs) }) => f x.val) = map f xs
theorem List.map₂_eq_map_snd {γ : Type u_1} {α : Type u} {β : Type v} [SizeOf α] [SizeOf β] {xs : List (α × β)} (f : βγ) :
(xs.map₂ fun (x : { x : α × β // sizeOf x.snd < 1 + sizeOf xs }) => match x with | (a, b), property => (a, f b)) = map (fun (x : α × β) => match x with | (a, b) => (a, f b)) xs

Not actually a special case of map₂_eq_map -- you can use this in places you can't use map₂_eq_map because the LHS function (being mapped) doesn't fit the map₂_eq_map form but does fit this form (where the application of f is not the outermost AST node of the function, basically)

theorem List.map₃_eq_map_snd {α : Type u_1} {β : Type u_2} {γ : Type u_3} [SizeOf α] [SizeOf β] {xs : List (α × β)} (f : βγ) :
(xs.map₃ fun (x : { x : α × β // sizeOf x.snd < 1 + (1 + sizeOf xs) }) => match x with | (a, b), property => (a, f b)) = map (fun (x : α × β) => match x with | (a, b) => (a, f b)) xs

same as map₂_eq_map_snd but for map₃

flatMap #

theorem List.exists_iff_mem_flatMap {α : Type u_1} {β : Type u_2} [DecidableEq β] {f : αList β} {xs : List α} {b : β} :
b flatMap f xs (a : α), a xs b f a

As of this writing, the standard-library lemma List.exists_of_mem_flatMap is a , but it's trivial to extend it to and makes some things easier, so we do that here

Forall₂ #

theorem List.forall₂_nil_left_iff {α✝ : Type u_1} {α✝¹ : Type u_2} {R : α✝α✝¹Prop} {l : List α✝¹} :

Copied from Mathlib

theorem List.forall₂_nil_right_iff {α✝ : Type u_1} {β✝ : Type u_2} {R : α✝β✝Prop} {l : List α✝} :

Copied from Mathlib

theorem List.Forall₂.imp {α✝ : Type u_1} {α✝¹ : Type u_2} {R S : α✝α✝¹Prop} (H : ∀ (a : α✝) (b : α✝¹), R a bS a b) {l₁ : List α✝} {l₂ : List α✝¹} (h : Forall₂ R l₁ l₂) :
Forall₂ S l₁ l₂

Copied from Mathlib

theorem List.forall₂_cons_left_iff {α✝ : Type u_1} {α✝¹ : Type u_2} {R : α✝α✝¹Prop} {a : α✝} {l : List α✝} {u : List α✝¹} :
Forall₂ R (a :: l) u (b : α✝¹), (u' : List α✝¹), R a b Forall₂ R l u' u = b :: u'

Copied from Mathlib

theorem List.forall₂_cons_right_iff {α✝ : Type u_1} {α✝¹ : Type u_2} {R : α✝α✝¹Prop} {b : α✝¹} {l : List α✝¹} {u : List α✝} :
Forall₂ R u (b :: l) (a : α✝), (u' : List α✝), R a b Forall₂ R u' l u = a :: u'

Copied from Mathlib

theorem List.forall₂_singleton_right_iff {α : Type u_1} {β : Type u_2} {R : αβProp} {xs : List α} {y : β} :
Forall₂ R xs [y] (x : α), R x y xs = [x]
theorem List.forall₂_pair_right_iff {α : Type u_1} {β : Type u_2} {R : αβProp} {xs : List α} {y₁ y₂ : β} :
Forall₂ R xs [y₁, y₂] (x₁ : α), (x₂ : α), R x₁ y₁ R x₂ y₂ xs = [x₁, x₂]
theorem List.forall₂_implies_all_left {α : Type u_1} {β : Type u_2} {R : αβProp} {xs : List α} {ys : List β} :
Forall₂ R xs ys∀ (x : α), x xs (y : β), y ys R x y

Note the converse is not true: counterexample R is =, xs is [1], ys is [1, 2]

theorem List.forall₂_implies_all_right {α : Type u_1} {β : Type u_2} {R : αβProp} {xs : List α} {ys : List β} :
Forall₂ R xs ys∀ (y : β), y ys (x : α), x xs R x y
theorem List.forall₂_iff_map_eq {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αγ} {g : βγ} {xs : List α} {ys : List β} :
Forall₂ (fun (x : α) (y : β) => f x = g y) xs ys map f xs = map g ys
theorem List.forall₂_fun_subset_implies {α : Type u_1} {β : Type u_2} {R : αβProp} {xs xs' : List α} {ys ys' : List β} :
Forall₂ R xs ysForall₂ R xs' ys'(∀ {x : α} {y y' : β}, R x yR x y'y = y')xs xs'ys ys'
theorem List.forall₂_fun_equiv_implies {α : Type u_1} {β : Type u_2} {R : αβProp} {xs xs' : List α} {ys ys' : List β} :
Forall₂ R xs ysForall₂ R xs' ys'(∀ {x : α} {y y' : β}, R x yR x y'y = y')xs xs'ys ys'

The converse (ys ≡ ys' → xs ≡ xs') doesn't hold without requiring R to be injective (as well as functional).

theorem List.map_preserves_forall₂ {α : Type u_1} {α' : Type u_2} {β : Type u_3} {β' : Type u_4} {f : αα'} {g : ββ'} {p₁ : αβProp} {p₂ : α'β'Prop} {xs : List α} {ys : List β} (h : ∀ (x : α) (y : β), p₁ x yp₂ (f x) (g y)) (hforall₂ : Forall₂ p₁ xs ys) :
Forall₂ p₂ (map f xs) (map g ys)
theorem List.forall₂_swap {α : Type u_1} {β : Type u_2} {R : αβProp} {xs : List α} {ys : List β} (hforall₂ : Forall₂ (fun (y : β) (x : α) => R x y) ys xs) :
Forall₂ R xs ys
theorem List.forall₂_compose_mapM_right {α : Type u_1} {β : Type u_2} {γ : Type u_3} {l₁ : List α} {l₂ : List β} {l₃ : List γ} {R₁ : αβProp} {R₂ : αγProp} {f : βOption γ} (h : Forall₂ R₁ l₁ l₂) (hmapM : mapM f l₂ = some l₃) (hf : ∀ (a : α) (b : β), R₁ a b (c : γ), f b = some c R₂ a c) :
Forall₂ R₂ l₁ l₃

Applying mapM on the RHS list of Forall₂ leads to new Forall₂ relation if certain conditions are met.

theorem List.forall₂_eq_implies_filterMap {α : Type u_1} {β : Type u_2} {l₁ : List α} {l₂ : List β} {p : αβProp} {f : αOption β} (h : Forall₂ p l₁ l₂) (hp : ∀ (a : α) (b : β), p a bf a = some b) :
filterMap f l₁ = l₂
theorem List.forall₂_trans_ish {α : Type u_1} {β : Type u_2} {γ : Type u_3} {xs : List α} {ys : List β} {zs : List γ} {Q : αβProp} {R : αγProp} {S : βγProp} (h₁ : Forall₂ Q xs ys) (h₂ : Forall₂ R xs zs) :
(∀ {a : α} {b : β} {c : γ}, Q a bR a cS b c)Forall₂ S ys zs

kind of a transitivity property, if you squint

mapM, mapM', mapM₁, and mapM₂ #

theorem List.mapM_some {α : Type u_1} {xs : List α} :
mapM some xs = some xs
theorem List.mapM₁_eq_mapM {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (f : αm β) (as : List α) :
(as.mapM₁ fun (x : { x : α // x as }) => f x.val) = mapM f as
theorem List.mapM₂_eq_mapM {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_4} {γ : Type u_1} [Monad m] [LawfulMonad m] [SizeOf α] [SizeOf β] (f : α × βm γ) (as : List (α × β)) :
(as.mapM₂ fun (x : { _x : α × β // sizeOf _x.snd < 1 + sizeOf as }) => f x.val) = mapM f as
theorem List.mapM₂_eq_map_snd {m : Type (max u_1 u) → Type u_2} {γ : Type (max u_1 u)} {α : Type u} {β : Type v} [SizeOf α] [SizeOf β] [Monad m] [LawfulMonad m] {xs : List (α × β)} (f : βm γ) :
(xs.mapM₂ fun (x : { x : α × β // sizeOf x.snd < 1 + sizeOf xs }) => match x with | (a, b), property => do let __do_liftf b pure (a, __do_lift)) = mapM (fun (x : α × β) => match x with | (a, b) => do let __do_liftf b pure (a, __do_lift)) xs

See notes on map₂_eq_map_snd. This has a similar relationship to mapM₂_eq_mapM as map₂_eq_map_snd does to map₂_eq_map.

theorem List.mapM₃_eq_mapM {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_4} {γ : Type u_1} [Monad m] [LawfulMonad m] [SizeOf α] [SizeOf β] (f : α × βm γ) (as : List (α × β)) :
(as.mapM₃ fun (x : { x : α × β // sizeOf x.snd < 1 + (1 + sizeOf as) }) => f x.val) = mapM f as
theorem List.mapM_implies_nil {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept β γ} {as : List α} (h₁ : mapM f as = Except.ok []) :
as = []
theorem List.mapM_head_tail {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept β γ} {x : α} {xs : List α} {y : γ} {ys : List γ} :
mapM f (x :: xs) = Except.ok (y :: ys)mapM f xs = Except.ok ys
theorem List.mapM'_preserves_length {α✝ : Type u_1} {ε✝ : Type u_2} {α✝¹ : Type u_3} {f : α✝Except ε✝ α✝¹} {xs : List α✝} {ys : List α✝¹} :
mapM' f xs = Except.ok ysxs.length = ys.length
theorem List.mapM_preserves_length {α✝ : Type u_1} {ε✝ : Type u_2} {α✝¹ : Type u_3} {f : α✝Except ε✝ α✝¹} {xs : List α✝} {ys : List α✝¹} :
mapM f xs = Except.ok ysxs.length = ys.length
theorem List.not_mem_implies_not_mem_mapM_key_id {α β : Type} {ks : List α} {kvs : List (α × β)} {fn : αOption β} {k : α} (hm : mapM (fun (k : α) => do let __do_liftfn k some (k, __do_lift)) ks = some kvs) (hl : ¬k ks) (v : β) :
¬(k, v) kvs
theorem List.mapM'_ok_iff_forall₂ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} {ys : List β} :
mapM' f xs = Except.ok ys Forall₂ (fun (x : α) (y : β) => f x = Except.ok y) xs ys
theorem List.mapM'_some_iff_forall₂ {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} {ys : List β} :
mapM' f xs = some ys Forall₂ (fun (x : α) (y : β) => f x = some y) xs ys

Copy of mapM'_ok_iff_forall₂ but for option instead of exception

theorem List.mapM_ok_iff_forall₂ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} {ys : List β} :
mapM f xs = Except.ok ys Forall₂ (fun (x : α) (y : β) => f x = Except.ok y) xs ys
theorem List.mapM_some_iff_forall₂ {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} {ys : List β} :
mapM f xs = some ys Forall₂ (fun (x : α) (y : β) => f x = some y) xs ys
theorem List.mapM_implies_forall₂ {α : Type u_1} {ε : Type u_2} {β : Type u_3} {f : αExcept ε β} {p : αβProp} {xs : List α} {ys : List β} (h : ∀ (x : α) (y : β), x xsf x = Except.ok yp x y) (hmapM : mapM f xs = Except.ok ys) :
Forall₂ p xs ys

Introduces forall₂ through the input output relation of a f through List.mapM. This is slightly stronger than the forward direction of mapM_ok_iff_forall₂ since it allowed an extra x ∈ xs condition in h.

theorem List.mapM_implies_forall₂_option {α : Type u_1} {β : Type u_2} {f : αOption β} {p : αβProp} {xs : List α} {ys : List β} (h : ∀ (x : α) (y : β), x xsf x = some yp x y) (hmapM : mapM f xs = some ys) :
Forall₂ p xs ys

Same as mapM_implies_forall₂ but for Option

theorem List.mapM'_ok_implies_all_ok {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} {ys : List β} :
mapM' f xs = Except.ok ys∀ (x : α), x xs (y : β), y ys f x = Except.ok y

Note that the converse is not true: counterexample xs is [1], ys is [1, 2], f is Except.ok

But for a limited converse, see all_ok_implies_mapM'_ok

theorem List.mapM_ok_implies_all_ok {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} {ys : List β} :
mapM f xs = Except.ok ys∀ (x : α), x xs (y : β), y ys f x = Except.ok y
theorem List.all_ok_implies_mapM'_ok {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} :
(∀ (x : α), x xs (y : β), f x = Except.ok y) (ys : List β), mapM' f xs = Except.ok ys
theorem List.all_ok_implies_mapM_ok {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} :
(∀ (x : α), x xs (y : β), f x = Except.ok y) (ys : List β), mapM f xs = Except.ok ys
theorem List.mapM'_ok_implies_all_from_ok {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} {ys : List β} :
mapM' f xs = Except.ok ys∀ (y : β), y ys (x : α), x xs f x = Except.ok y

Note that the converse is not true: counterexample ys is [1], xs is [1, 2], f is Except.ok

But for a limited converse, see all_from_ok_implies_mapM'_ok

theorem List.mapM_ok_implies_all_from_ok {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} {ys : List β} :
mapM f xs = Except.ok ys∀ (y : β), y ys (x : α), x xs f x = Except.ok y
theorem List.all_from_ok_implies_mapM'_ok {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {ys : List β} :
(∀ (y : β), y ys (x : α), f x = Except.ok y) (xs : List α), mapM' f xs = Except.ok ys
theorem List.all_from_ok_implies_mapM_ok {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {ys : List β} :
(∀ (y : β), y ys (x : α), f x = Except.ok y) (xs : List α), mapM f xs = Except.ok ys
theorem List.mapM'_error_implies_exists_error {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} {e : γ} :
mapM' f xs = Except.error e (x : α), x xs f x = Except.error e

The converse is not true: counterexample xs is [1, 2] and f is Except.error. In that case, f 2 = .error 2 but xs.mapM' f = .error 1.

But for a limited converse, see element_error_implies_mapM_error

theorem List.mapM_error_implies_exists_error {α : Type u_1} {β : Type u_2} {γ : Type u_3} {f : αExcept γ β} {xs : List α} {e : γ} :
mapM f xs = Except.error e (x : α), x xs f x = Except.error e
theorem List.filterMapM_error_implies_exists_error {α : Type u_1} {β : Type u_2} {ε : Type u_3} {f : αExcept ε (Option β)} {xs : List α} {e : ε} :
filterMapM f xs = Except.error e (x : α), x xs f x = Except.error e
theorem List.element_error_implies_mapM'_error {α : Type u_1} {ε : Type u_2} {β : Type u_3} {x : α} {xs : List α} {f : αExcept ε β} {e : ε} :
x xsf x = Except.error e (e' : ε), mapM' f xs = Except.error e'

If applying f to any of xs produces an error, then xs.mapM' f must also produce an error (not necessarily the same error)

Limited converse of mapM'_error_implies_exists_error

theorem List.element_error_implies_mapM_error {α : Type u_1} {ε : Type u_2} {β : Type u_3} {x : α} {xs : List α} {f : αExcept ε β} {e : ε} :
x xsf x = Except.error e (e' : ε), mapM f xs = Except.error e'
theorem List.element_to_option_none_implies_mapM_none {α : Type u_1} {β : Type u_2} {ε : Type u_3} {ls : List α} {x : α} {f : αExcept ε β} (h₁ : x ls) (h₂ : (f x).toOption = none) :
theorem List.mapM'_ok_eq_filterMap {ε : Type u_1} {α : Type u_2} {β : Type u_3} {f : αExcept ε β} {xs : List α} {ys : List β} :
mapM' f xs = Except.ok ysfilterMap (fun (x : α) => match f x with | Except.ok y => some y | Except.error a => none) xs = ys
theorem List.mapM_ok_eq_filterMap {ε : Type u_1} {α : Type u_2} {β : Type u_3} {f : αExcept ε β} {xs : List α} {ys : List β} :
mapM f xs = Except.ok ysfilterMap (fun (x : α) => match f x with | Except.ok y => some y | Except.error a => none) xs = ys
theorem List.mapM'_some_implies_all_some {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} {ys : List β} :
mapM' f xs = some ys∀ (x : α), x xs (y : β), y ys f x = some y

Note that the converse is not true: counterexample xs is [1], ys is [1, 2], f is Option.some

But for a limited converse, see all_some_implies_mapM'_some

theorem List.mapM_some_implies_all_some {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} {ys : List β} :
mapM f xs = some ys∀ (x : α), x xs (y : β), y ys f x = some y
theorem List.mem_mapM_some_implies_exists_unmapped_helper {α : Type u_1} {β : Type u_2} {y : β} {f : αOption β} {xs : List α} {ys : List β} :
Forall₂ (fun (x : α) (y : β) => f x = some y) xs ysy ys (x : α), x xs f x = some y
theorem List.mem_mapM_some_implies_exists_unmapped {α : Type u_1} {β : Type u_2} {y : β} {f : αOption β} {xs : List α} {ys : List β} :
mapM f xs = some ysy ys (x : α), x xs f x = some y
theorem List.all_some_implies_mapM'_some {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} :
(∀ (x : α), x xs (y : β), f x = some y) (ys : List β), mapM' f xs = some ys
theorem List.all_some_implies_mapM_some {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} :
(∀ (x : α), x xs (y : β), f x = some y) (ys : List β), mapM f xs = some ys
theorem List.mapM'_some_implies_all_from_some {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} {ys : List β} :
mapM' f xs = some ys∀ (y : β), y ys (x : α), x xs f x = some y

Note that the converse is not true: counterexample ys is [1], xs is [1, 2], f is Option.some

But for a limited converse, see all_from_some_implies_mapM'_some

theorem List.mapM_some_implies_all_from_some {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} {ys : List β} :
mapM f xs = some ys∀ (y : β), y ys (x : α), x xs f x = some y
theorem List.all_from_some_implies_mapM'_some {α : Type u_1} {β : Type u_2} {f : αOption β} {ys : List β} :
(∀ (y : β), y ys (x : α), f x = some y) (xs : List α), mapM' f xs = some ys
theorem List.all_from_some_implies_mapM_some {α : Type u_1} {β : Type u_2} {f : αOption β} {ys : List β} :
(∀ (y : β), y ys (x : α), f x = some y) (xs : List α), mapM f xs = some ys
theorem List.mapM'_none_iff_exists_none {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} :
mapM' f xs = none (x : α), x xs f x = none
theorem List.mapM_none_iff_exists_none {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} :
mapM f xs = none (x : α), x xs f x = none
theorem List.mapM'_some_eq_filterMap {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} {ys : List β} :
mapM' f xs = some ysfilterMap f xs = ys
theorem List.mapM_some_eq_filterMap {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} {ys : List β} :
mapM f xs = some ysfilterMap f xs = ys
theorem List.mapM'_some_subset {α : Type u_1} {β : Type u_2} {f : αOption β} {xs xs' : List α} {ys : List β} :
mapM' f xs = some ysxs' xs (ys' : List β), mapM' f xs' = some ys'
theorem List.mapM_some_subset {α : Type u_1} {β : Type u_2} {f : αOption β} {xs xs' : List α} {ys : List β} :
mapM f xs = some ysxs' xs (ys' : List β), mapM f xs' = some ys'
theorem List.forall₂_implies_mapM_eq {α₁ : Type u_1} {α₂ : Type u_2} {β : Type u_3} {ε : Type u_4} {xs : List α₁} {ys : List α₂} (f : α₁Except ε β) (g : α₂Except ε β) :
Forall₂ (fun (x : α₁) (y : α₂) => f x = g y) xs ysmapM f xs = mapM g ys
theorem List.mapM'_congr {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] {f g : αm β} {l : List α} :
(∀ (x : α), x lf x = g x)mapM' f l = mapM' g l

our own variant of map_congr, for mapM'

theorem List.mapM_congr {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] {f g : αm β} {l : List α} :
(∀ (x : α), x lf x = g x)mapM f l = mapM g l

our own variant of map_congr, for mapM

theorem List.to_option_distr_mapM' {α : Type u_1} {β : Type u_2} {ε : Type u_3} {l : List α} {f : αExcept ε β} :
theorem List.to_option_distr_mapM {α : Type u_1} {β : Type u_2} {ε : Type u_3} {l : List α} {f : αExcept ε β} :
theorem List.mapM_to_option_congr {α : Type u_1} {β : Type u_2} {ε₁ : Type u_3} {ε₂ : Type u_4} {l : List α} {f : αExcept ε₁ β} {g : αExcept ε₂ β} :
(∀ (x : α), x l(f x).toOption = (g x).toOption)(mapM f l).toOption = (mapM g l).toOption

foldl #

theorem List.foldl_pmap_subtype {α : Type u_1} {β : Type u_2} {p : αProp} (f : βαβ) (as : List α) (init : β) (h : ∀ (a : α), a asp a) :
foldl (fun (b : β) (x : { a : α // p a }) => f b x.val) init (pmap Subtype.mk as h) = foldl f init as
theorem List.foldl_congr {β : Type u_1} {α : Type u_2} {f g : βαβ} {init : β} {l : List α} :
(∀ (b : β) (x : α), x lf b x = g b x)foldl f init l = foldl g init l

foldlM #

theorem List.foldlM_of_assoc_some {α : Type u_1} (f : ααOption α) (x₀ x₁ x₂ x₃ : α) (xs : List α) (h₁ : ∀ (x₁ x₂ x₃ : α), (do let x₄f x₁ x₂ f x₄ x₃) = do let x₄f x₂ x₃ f x₁ x₄) (h₂ : f x₀ x₁ = some x₂) (h₃ : foldlM f x₂ xs = some x₃) :
(do let yfoldlM f x₁ xs f x₀ y) = some x₃
theorem List.foldlM_of_assoc_none' {α : Type u_1} (f : ααOption α) (x₀ x₁ x₂ : α) (xs : List α) (h₁ : ∀ (x₁ x₂ x₃ : α), (do let x₄f x₁ x₂ f x₄ x₃) = do let x₄f x₂ x₃ f x₁ x₄) (h₂ : f x₀ x₁ = none) (h₃ : foldlM f x₁ xs = some x₂) :
f x₀ x₂ = none
theorem List.foldlM_of_assoc_none {α : Type u_1} (f : ααOption α) (x₀ x₁ x₂ : α) (xs : List α) (h₁ : ∀ (x₁ x₂ x₃ : α), (do let x₄f x₁ x₂ f x₄ x₃) = do let x₄f x₂ x₃ f x₁ x₄) (h₂ : f x₀ x₁ = some x₂) (h₃ : foldlM f x₂ xs = none) :
(do let yfoldlM f x₁ xs f x₀ y) = none
theorem List.foldlM_of_assoc {α : Type u_1} (f : ααOption α) (x₀ x₁ : α) (xs : List α) (h₁ : ∀ (x₁ x₂ x₃ : α), (do let x₄f x₁ x₂ f x₄ x₃) = do let x₄f x₂ x₃ f x₁ x₄) :
foldlM f x₀ (x₁ :: xs) = do let yfoldlM f x₁ xs f x₀ y

find? #

theorem List.find?_pair_map {α : Type u_1} {β : Type u_2} {γ : Type u_3} [BEq α] (f : βγ) (xs : List (α × β)) (k : α) :
Option.map (fun (x : α × β) => (x.fst, f x.snd)) (find? (fun (x : α × β) => x.fst == k) xs) = find? (fun (x : α × γ) => x.fst == k) (map (fun (x : α × β) => (x.fst, f x.snd)) xs)
theorem List.find?_fst_map_implies_find? {α : Type u_1} {β : Type u_2} {γ : Type u_3} [BEq α] {f : βγ} {xs : List (α × β)} {k : α} {fx : α × γ} :
find? (fun (x : α × γ) => x.fst == k) (map (Prod.map id f) xs) = some fx (x : α × β), find? (fun (x : α × β) => x.fst == k) xs = some x fx = Prod.map id f x
theorem List.find?_implies_find?_fst_map {α : Type u_1} {β : Type u_2} {γ : Type u_3} [BEq α] [ReflBEq α] {l : List (α × β)} {k : α} {v : β} {f : αβγ} (h : find? (fun (x : α × β) => x.fst == k) l = some (k, v)) :
find? (fun (x : α × γ) => x.fst == k) (map (fun (x : α × β) => match x with | (k, v) => (k, f k v)) l) = some (k, f k v)
theorem List.find?_implies_append_find? {α : Type u_1} {a b : List α} {v : α} {f : αBool} (h : find? f a = some v) :
find? f (a ++ b) = some v
theorem List.not_find?_some_iff_find?_none {α : Type u_1} {p : αBool} {xs : List α} :
(∀ (x : α), x xs¬find? p xs = some x) find? p xs = none
theorem List.find?_exact_iff_mem {α : Type u_1} [DecidableEq α] {l : List α} {v : α} :
find? (fun (x : α) => x == v) l = some v v l

filterMap #

theorem List.filterMap_congr {α : Type u_1} {β : Type u_2} {f g : αOption β} {l : List α} :
(∀ (x : α), x lf x = g x)filterMap f l = filterMap g l

our own variant of map_congr, for filterMap

theorem List.filterMap_empty_iff_all_none {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} :
filterMap f xs = [] ∀ (x : α), x xsf x = none
theorem List.filterMap_nonempty_iff_exists_some {α : Type u_1} {β : Type u_2} {f : αOption β} {xs : List α} :
filterMap f xs [] (x : α), x xs (f x).isSome = true
theorem List.f_implies_g_then_subset {α : Type u_1} {β : Type u_2} {f g : αOption β} {xs : List α} :
(∀ (a : α) (b : β), f a = some bg a = some b)filterMap f xs filterMap g xs

forM and mapM #

theorem List.mapM_forM {α β : Type} (f : αExcept β PUnit) (xs : List α) (ys : List PUnit) :
mapM f xs = Except.ok ysxs.forM f = Except.ok ()
theorem List.forM_mapM {α β : Type} (f : αExcept β PUnit) (xs : List α) :
theorem List.forM_ok_implies_all_ok {α β : Type} (xs : List α) (f : αExcept β Unit) :
xs.forM f = Except.ok ()∀ (x : α), x xsf x = Except.ok ()
theorem List.forM_ok_implies_all_ok' {α β : Type} {xs : List α} {f : αExcept β Unit} :
xs.forM f = Except.ok ()∀ (x : α), x xsf x = Except.ok ()
theorem List.all_ok_implies_forM_ok {α β : Type} (xs : List α) (f : αExcept β Unit) :
(∀ (x : α), x xsf x = Except.ok ())xs.forM f = Except.ok ()

removeAll #

theorem List.removeAll_singleton_cons_of_neq {α : Type u_1} [DecidableEq α] (x y : α) (xs : List α) :
x y(x :: xs).removeAll [y] = x :: xs.removeAll [y]
theorem List.removeAll_singleton_cons_of_eq {α : Type u_1} [DecidableEq α] (x : α) (xs : List α) :
(x :: xs).removeAll [x] = xs.removeAll [x]
theorem List.mem_removeAll_singleton_of_eq {α : Type u_1} [DecidableEq α] (x : α) (xs : List α) :
theorem List.removeAll_singleton_equiv {α : Type u_1} [DecidableEq α] (x : α) (xs : List α) :
x :: xs x :: xs.removeAll [x]
theorem List.length_removeAll_le {α : Type u_1} [BEq α] (xs ys : List α) :
theorem List.mem_pmap_subtype {α : Type u_1} {p : αProp} (as : List α) (h : ∀ (a : α), a asp a) (a : α) (ha : p a) :
a, ha pmap Subtype.mk as h a as
theorem List.find?_compose {α : Type u_1} {β : Sort u_2} (f : αβ) (p₁ : βBool) (p₂ : αBool) {xs : List α} :
(∀ (x : α), (p₁ f) x = p₂ x)find? (p₁ f) xs = find? p₂ xs
@[irreducible]
theorem List.mem_implies_mem_eraseDups {α : Type u_1} [BEq α] [LawfulBEq α] {xs : List α} {x : α} (hmem : x xs) :
@[irreducible]
theorem List.mem_eraseDups_implies_mem {α : Type u_1} [BEq α] [LawfulBEq α] {xs : List α} {x : α} (hmem : x xs.eraseDups) :
x xs
theorem List.mem_iff_mem_eraseDups {α : Type u_1} [BEq α] [LawfulBEq α] {xs : List α} {x : α} :
x xs x xs.eraseDups
theorem List.mapM_preserves_SortedBy {γ : Type u_1} {α : Type u_2} {β : Type u_3} [LT γ] {l₁ : List α} {l₂ : List β} {f : αOption β} {k₁ : αγ} {k₂ : βγ} (hsorted : SortedBy k₁ l₁) (hmapM : mapM f l₁ = some l₂) (hkey : ∀ (a : α) (b : β), f a = some bk₁ a = k₂ b) :
SortedBy k₂ l₂

mapM preserves SortedBy if the keys are preserved

theorem List.map_restricted_id {α : Type u_1} {l : List α} {f : αα} (hf : ∀ (x : α), x lf x = x) :
map f l = l
theorem List.findSome?_unique {α : Type u_1} {β : Type u_2} [BEq α] [LawfulBEq α] {l : List α} {x : α} {y : β} {f : αOption β} (hfind : x l) (hf : ∀ (x' : α), ( (y' : β), f x' = some y') → x' = x) (hx : f x = some y) :
theorem List.find?_unique_entry {α : Type u_1} {l : List α} {f : αBool} {v : α} (hf : ∀ (x : α), x lf x = truex = v) (hmem : v l) (hv : f v = true) :
find? f l = some v
theorem List.find?_stronger_pred {α : Type u_1} {l : List α} {v : α} {f g : αBool} (hfind : find? f l = some v) (hg : ∀ (x : α), x lg x = truef x = true) (hv : g v = true) :
find? g l = some v
theorem List.mem_of_map_implies_exists_unmapped {α : Type u_1} {β : Type u_2} {l : List α} {v₂ : β} {f : αβ} :
v₂ map f l (v₁ : α), v₁ l v₂ = f v₁
theorem List.mem_map_iff_find? {β : Type u_1} {α : Type u_2} [BEq β] [LawfulBEq β] {k : β} {f : αβ} {kvs : List α} :
k map f kvs (find? (fun (x : α) => f x == k) kvs).isSome = true
theorem List.mem_implies_find? {α : Type u_1} {l : List α} {k : α} {f : αBool} (hmem : k l) (hk : f k = true) (hf : ∀ (k' : α), f k' = truek' = k) :
find? f l = some k
theorem List.filterMap_eq_filterMap {α : Type u_1} {β : Type u_2} {γ : Type u_3} {l₁ : List α} {l₂ : List β} {p : αβProp} {f₁ : αOption γ} {f₂ : βOption γ} (h : Forall₂ p l₁ l₂) (hp : ∀ (a : α) (b : β), p a bf₁ a = f₂ b) :
filterMap f₁ l₁ = filterMap f₂ l₂
theorem List.find?_filter_if_find? {α : Type u} {β : Type v} [BEq α] [LawfulBEq α] {k : α} {val : β} {l : List (α × β)} (p : αβBool) :
find? (fun (x : α × β) => x.fst == k) l = some (k, val)p k val = truefind? (fun (x : α × β) => x.fst == k) (filter (fun (kv : α × β) => p kv.fst kv.snd) l) = some (k, val)
theorem List.find?_filter_sorted {α : Type u} {β : Type v} [BEq α] [LawfulBEq α] [DecidableEq α] [LT α] [Cedar.Data.StrictLT α] [DecidableLT α] (k : α) (val : β) (l : List (α × β)) (p : αβBool) :
SortedBy Prod.fst lfind? (fun (x : α × β) => x.fst == k) (filter (fun (kv : α × β) => p kv.fst kv.snd) l) = some (k, val)find? (fun (x : α × β) => x.fst == k) l = some (k, val) p k val = true
theorem List.anyM_some_implies_any {α : Type u_1} {xs : List α} {b : Bool} (f : αOption Bool) (g : αBool) :
(∀ (x : α) (b : Bool), f x = some bg x = b)anyM f xs = some bxs.any g = b