length #
mem #
append #
map #
bind #
join #
bounded quantifiers over Lists #
reverse #
nth element #
@[simp]
theorem
List.get?_map
{α : Type u_1}
{β : Type u_2}
(f : α → β)
(l : List α)
(n : Nat)
:
(List.map f l).get? n = Option.map f (l.get? n)
take and drop #
takeWhile and dropWhile #
theorem
List.dropWhile_cons
{α : Type u_1}
{x : α}
{xs : List α}
{p : α → Bool}
:
List.dropWhile p (x :: xs) = if p x = true then List.dropWhile p xs else x :: xs
foldlM and foldrM #
@[simp]
theorem
List.foldlM_reverse
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
[Monad m]
(l : List α)
(f : β → α → m β)
(b : β)
:
List.foldlM f b l.reverse = List.foldrM (fun (x : α) (y : β) => f y x) b l
@[simp]
theorem
List.foldlM_nil
{m : Type u_1 → Type u_2}
{β : Type u_1}
{α : Type u_3}
[Monad m]
(f : β → α → m β)
(b : β)
:
List.foldlM f b [] = pure b
@[simp]
theorem
List.foldlM_cons
{m : Type u_1 → Type u_2}
{β : Type u_1}
{α : Type u_3}
[Monad m]
(f : β → α → m β)
(b : β)
(a : α)
(l : List α)
:
List.foldlM f b (a :: l) = do
let init ← f b a
List.foldlM f init l
@[simp]
theorem
List.foldlM_append
{m : Type u_1 → Type u_2}
{β : Type u_1}
{α : Type u_3}
[Monad m]
[LawfulMonad m]
(f : β → α → m β)
(b : β)
(l : List α)
(l' : List α)
:
List.foldlM f b (l ++ l') = do
let init ← List.foldlM f b l
List.foldlM f init l'
@[simp]
theorem
List.foldrM_nil
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
[Monad m]
(f : α → β → m β)
(b : β)
:
List.foldrM f b [] = pure b
@[simp]
theorem
List.foldrM_cons
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
[Monad m]
[LawfulMonad m]
(a : α)
(l : List α)
(f : α → β → m β)
(b : β)
:
List.foldrM f b (a :: l) = List.foldrM f b l >>= f a
@[simp]
theorem
List.foldrM_reverse
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
[Monad m]
(l : List α)
(f : α → β → m β)
(b : β)
:
List.foldrM f b l.reverse = List.foldlM (fun (x : β) (y : α) => f y x) b l
theorem
List.foldl_eq_foldlM
{β : Type u_1}
{α : Type u_2}
(f : β → α → β)
(b : β)
(l : List α)
:
List.foldl f b l = List.foldlM f b l
theorem
List.foldr_eq_foldrM
{α : Type u_1}
{β : Type u_2}
(f : α → β → β)
(b : β)
(l : List α)
:
List.foldr f b l = List.foldrM f b l
foldl and foldr #
@[simp]
theorem
List.foldl_reverse
{α : Type u_1}
{β : Type u_2}
(l : List α)
(f : β → α → β)
(b : β)
:
List.foldl f b l.reverse = List.foldr (fun (x : α) (y : β) => f y x) b l
@[simp]
theorem
List.foldr_reverse
{α : Type u_1}
{β : Type u_2}
(l : List α)
(f : α → β → β)
(b : β)
:
List.foldr f b l.reverse = List.foldl (fun (x : β) (y : α) => f y x) b l
@[simp]
theorem
List.foldrM_append
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
[Monad m]
[LawfulMonad m]
(f : α → β → m β)
(b : β)
(l : List α)
(l' : List α)
:
List.foldrM f b (l ++ l') = do
let init ← List.foldrM f b l'
List.foldrM f init l
@[simp]
theorem
List.foldl_append
{α : Type u_1}
{β : Type u_2}
(f : β → α → β)
(b : β)
(l : List α)
(l' : List α)
:
List.foldl f b (l ++ l') = List.foldl f (List.foldl f b l) l'
@[simp]
theorem
List.foldr_append
{α : Type u_1}
{β : Type u_2}
(f : α → β → β)
(b : β)
(l : List α)
(l' : List α)
:
List.foldr f b (l ++ l') = List.foldr f (List.foldr f b l') l
@[simp]
theorem
List.foldl_nil :
∀ {α : Type u_1} {β : Type u_2} {f : α → β → α} {b : α}, List.foldl f b [] = b
@[simp]
theorem
List.foldl_cons
{α : Type u_1}
{β : Type u_2}
{a : α}
{f : β → α → β}
(l : List α)
(b : β)
:
List.foldl f b (a :: l) = List.foldl f (f b a) l
@[simp]
theorem
List.foldr_nil :
∀ {α : Type u_1} {α_1 : Type u_2} {f : α → α_1 → α_1} {b : α_1}, List.foldr f b [] = b
@[simp]
theorem
List.foldr_cons
{α : Type u_1}
{a : α}
:
∀ {α_1 : Type u_2} {f : α → α_1 → α_1} {b : α_1} (l : List α), List.foldr f b (a :: l) = f a (List.foldr f b l)
@[simp]
theorem
List.foldr_self_append
{α : Type u_1}
{l' : List α}
(l : List α)
:
List.foldr List.cons l' l = l ++ l'
theorem
List.foldl_map
{β₁ : Type u_1}
{β₂ : Type u_2}
{α : Type u_3}
(f : β₁ → β₂)
(g : α → β₂ → α)
(l : List β₁)
(init : α)
:
List.foldl g init (List.map f l) = List.foldl (fun (x : α) (y : β₁) => g x (f y)) init l
theorem
List.foldr_map
{α₁ : Type u_1}
{α₂ : Type u_2}
{β : Type u_3}
(f : α₁ → α₂)
(g : α₂ → β → β)
(l : List α₁)
(init : β)
:
List.foldr g init (List.map f l) = List.foldr (fun (x : α₁) (y : β) => g (f x) y) init l
mapM #
Alternate (non-tail-recursive) form of mapM for proofs.
Equations
- List.mapM' f [] = pure []
- List.mapM' f (a :: l) = do let __do_lift ← f a let __do_lift_1 ← List.mapM' f l pure (__do_lift :: __do_lift_1)
Instances For
@[simp]
theorem
List.mapM'_nil
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
[Monad m]
{f : α → m β}
:
List.mapM' f [] = pure []
@[simp]
theorem
List.mapM'_cons
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
{a : α}
{l : List α}
[Monad m]
{f : α → m β}
:
List.mapM' f (a :: l) = do
let __do_lift ← f a
let __do_lift_1 ← List.mapM' f l
pure (__do_lift :: __do_lift_1)
theorem
List.mapM'_eq_mapM
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
[Monad m]
[LawfulMonad m]
(f : α → m β)
(l : List α)
:
List.mapM' f l = List.mapM f l
theorem
List.mapM'_eq_mapM.go
{m : Type u_1 → Type u_2}
{α : Type u_3}
{β : Type u_1}
[Monad m]
[LawfulMonad m]
(f : α → m β)
(l : List α)
(acc : List β)
:
List.mapM.loop f l acc = do
let __do_lift ← List.mapM' f l
pure (acc.reverse ++ __do_lift)
forM #
@[simp]
theorem
List.forM_nil'
{m : Type u_1 → Type u_2}
{α : Type u_3}
{f : α → m PUnit}
[Monad m]
:
[].forM f = pure PUnit.unit
eraseIdx #
find? #
theorem
List.find?_cons :
∀ {α : Type u_1} {a : α} {as : List α} {p : α → Bool},
List.find? p (a :: as) = match p a with
| true => some a
| false => List.find? p as
filter #
@[simp]
theorem
List.filter_cons_of_pos
{α : Type u_1}
{p : α → Bool}
{a : α}
(l : List α)
(pa : p a = true)
:
List.filter p (a :: l) = a :: List.filter p l
@[simp]
theorem
List.filter_cons_of_neg
{α : Type u_1}
{p : α → Bool}
{a : α}
(l : List α)
(pa : ¬p a = true)
:
List.filter p (a :: l) = List.filter p l
theorem
List.filter_cons
{α : Type u_1}
{x : α}
{xs : List α}
{p : α → Bool}
:
List.filter p (x :: xs) = if p x = true then x :: List.filter p xs else List.filter p xs
findSome? #
@[simp]
theorem
List.findSome?_nil
{α : Type u_1}
:
∀ {α_1 : Type u_2} {f : α → Option α_1}, List.findSome? f [] = none
theorem
List.findSome?_cons
{α : Type u_1}
{β : Type u_2}
{a : α}
{as : List α}
{f : α → Option β}
:
List.findSome? f (a :: as) = match f a with
| some b => some b
| none => List.findSome? f as
replace #
elem #
lookup #
@[simp]
zipWith #
@[simp]
theorem
List.zipWith_nil_left
{α : Type u_1}
{β : Type u_2}
{γ : Type u_3}
{l : List β}
{f : α → β → γ}
:
List.zipWith f [] l = []
@[simp]
theorem
List.zipWith_nil_right
{α : Type u_1}
{β : Type u_2}
{γ : Type u_3}
{l : List α}
{f : α → β → γ}
:
List.zipWith f l [] = []
@[simp]
theorem
List.zipWith_cons_cons
{α : Type u_1}
{β : Type u_2}
{γ : Type u_3}
{a : α}
{as : List α}
{b : β}
{bs : List β}
{f : α → β → γ}
:
List.zipWith f (a :: as) (b :: bs) = f a b :: List.zipWith f as bs
zipWithAll #
zip #
unzip #
all / any #
enumFrom #
@[simp]
theorem
List.enumFrom_cons :
∀ {α : Type u_1} {a : α} {as : List α} {i : Nat}, List.enumFrom i (a :: as) = (i, a) :: List.enumFrom (i + 1) as
iota #
intersperse #
@[simp]
@[simp]
theorem
List.intersperse_cons₂
{α : Type u_1}
{x : α}
{y : α}
{zs : List α}
(sep : α)
:
List.intersperse sep (x :: y :: zs) = x :: sep :: List.intersperse sep (y :: zs)
isPrefixOf #
isEqv #
dropLast #
minimum? #
theorem
List.minimum?_cons
{α : Type u_1}
{x : α}
[Min α]
{xs : List α}
:
(x :: xs).minimum? = some (List.foldl min x xs)
Basic properties of Lists #
length #
mem #
drop #
isEmpty #
append #
concat #
map #
zipWith #
@[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 β)
:
List.zipWith f (List.map g l₁) (List.map h l₂) = List.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 : α' → β → γ)
:
List.zipWith g (List.map f l₁) l₂ = List.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 : α → β' → γ)
:
List.zipWith g l₁ (List.map f l₂) = List.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 β}
{g : γ → δ → δ}
{f : α → β → γ}
(i : δ)
:
List.foldr g i (List.zipWith f l₁ l₂) = List.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 β}
{g : δ → γ → δ}
{f : α → β → γ}
(i : δ)
:
List.foldl g i (List.zipWith f l₁ l₂) = List.foldl (fun (r : δ) (p : α × β) => g r (f p.fst p.snd)) i (l₁.zip l₂)
theorem
List.map_zipWith
{α : Type u_1}
{β : Type u_2}
{γ : Type u_3}
{δ : Type u_4}
(f : α → β)
(g : γ → δ → α)
(l : List γ)
(l' : List δ)
:
List.map f (List.zipWith g l l') = List.zipWith (fun (x : γ) (y : δ) => f (g x y)) l l'
theorem
List.zipWith_append
{α : Type u_1}
{β : Type u_2}
{γ : Type u_3}
(f : α → β → γ)
(l : List α)
(la : List α)
(l' : List β)
(lb : List β)
(h : l.length = l'.length)
:
List.zipWith f (l ++ la) (l' ++ lb) = List.zipWith f l l' ++ List.zipWith f la lb
zip #
join #
bind #
set-theoretic notation of Lists #
bounded quantifiers over Lists #
replicate #
theorem
List.replicate_succ
{α : Type u_1}
(a : α)
(n : Nat)
:
List.replicate (n + 1) a = a :: List.replicate n a
theorem
List.eq_of_mem_replicate
{α : Type u_1}
{a : α}
{b : α}
{n : Nat}
(h : b ∈ List.replicate n a)
:
b = a
theorem
List.eq_replicate_of_mem
{α : Type u_1}
{a : α}
{l : List α}
:
(∀ (b : α), b ∈ l → b = a) → l = List.replicate l.length a
getLast #
head #
tail #
getLast #
theorem
List.getLastD_eq_getLast?
{α : Type u_1}
(a : α)
(l : List α)
:
l.getLastD a = l.getLast?.getD a
@[simp]
@[simp]
dropLast #
NB: dropLast
is the specification for Array.pop
, so theorems about List.dropLast
are often used for theorems about Array.pop
.
nth element #
theorem
List.get_of_eq
{α : Type u_1}
{l : List α}
{l' : List α}
(h : l = l')
(i : Fin l.length)
:
l.get i = l'.get ⟨↑i, ⋯⟩
If one has get l i hi
in a formula and h : l = l'
, one can not rw h
in the formula as
hi
gives i < l.length
and not i < l'.length
. The theorem get_of_eq
can be used to make
such a rewrite, with rw [get_of_eq h]
.
@[simp]
theorem
List.get_replicate
{α : Type u_1}
(a : α)
{n : Nat}
(m : Fin (List.replicate n a).length)
:
(List.replicate n a).get m = a
set #
all / any #
reverse #
insert #
@[simp]
theorem
List.insert_of_mem
{α : Type u_1}
[BEq α]
[LawfulBEq α]
{a : α}
{l : List α}
(h : a ∈ l)
:
List.insert a l = l
@[simp]
theorem
List.mem_insert_self
{α : Type u_1}
[BEq α]
[LawfulBEq α]
(a : α)
(l : List α)
:
a ∈ List.insert a l
theorem
List.mem_insert_of_mem
{α : Type u_1}
[BEq α]
[LawfulBEq α]
{a : α}
{b : α}
{l : List α}
(h : a ∈ l)
:
a ∈ List.insert b l
@[simp]
theorem
List.length_insert_of_mem
{α : Type u_1}
[BEq α]
[LawfulBEq α]
{a : α}
{l : List α}
(h : a ∈ l)
:
(List.insert a l).length = l.length
erase #
filter and partition #
@[simp]
theorem
List.filter_append
{α : Type u_1}
{p : α → Bool}
(l₁ : List α)
(l₂ : List α)
:
List.filter p (l₁ ++ l₂) = List.filter p l₁ ++ List.filter p l₂
@[simp]
theorem
List.partition_eq_filter_filter
{α : Type u_1}
(p : α → Bool)
(l : List α)
:
List.partition p l = (List.filter p l, List.filter (not ∘ p) l)
theorem
List.partition_eq_filter_filter.aux
{α : Type u_1}
(p : α → Bool)
(l : List α)
{as : List α}
{bs : List α}
:
List.partition.loop p l (as, bs) = (as.reverse ++ List.filter p l, bs.reverse ++ List.filter (not ∘ p) l)
theorem
List.filter_congr'
{α : Type u_1}
{p : α → Bool}
{q : α → Bool}
{l : List α}
:
(∀ (x : α), x ∈ l → (p x = true ↔ q x = true)) → List.filter p l = List.filter q l
filterMap #
@[simp]
theorem
List.filterMap_nil
{α : Type u_1}
{β : Type u_2}
(f : α → Option β)
:
List.filterMap f [] = []
@[simp]
theorem
List.filterMap_cons
{α : Type u_1}
{β : Type u_2}
(f : α → Option β)
(a : α)
(l : List α)
:
List.filterMap f (a :: l) = match f a with
| none => List.filterMap f l
| some b => b :: List.filterMap f l
theorem
List.filterMap_cons_none
{α : Type u_1}
{β : Type u_2}
{f : α → Option β}
(a : α)
(l : List α)
(h : f a = none)
:
List.filterMap f (a :: l) = List.filterMap f l
theorem
List.filterMap_cons_some
{α : Type u_1}
{β : Type u_2}
(f : α → Option β)
(a : α)
(l : List α)
{b : β}
(h : f a = some b)
:
List.filterMap f (a :: l) = b :: List.filterMap f l
theorem
List.filterMap_append
{α : Type u_1}
{β : Type u_2}
(l : List α)
(l' : List α)
(f : α → Option β)
:
List.filterMap f (l ++ l') = List.filterMap f l ++ List.filterMap f l'
@[simp]
theorem
List.filterMap_eq_map
{α : Type u_1}
{β : Type u_2}
(f : α → β)
:
List.filterMap (some ∘ f) = List.map f
@[simp]
theorem
List.filterMap_eq_filter
{α : Type u_1}
(p : α → Bool)
:
List.filterMap (Option.guard fun (x : α) => p x = true) = List.filter p
theorem
List.filterMap_filterMap
{α : Type u_1}
{β : Type u_2}
{γ : Type u_3}
(f : α → Option β)
(g : β → Option γ)
(l : List α)
:
List.filterMap g (List.filterMap f l) = List.filterMap (fun (x : α) => (f x).bind g) l
theorem
List.map_filterMap
{α : Type u_1}
{β : Type u_2}
{γ : Type u_3}
(f : α → Option β)
(g : β → γ)
(l : List α)
:
List.map g (List.filterMap f l) = List.filterMap (fun (x : α) => Option.map g (f x)) l
@[simp]
theorem
List.filterMap_map
{α : Type u_1}
{β : Type u_2}
{γ : Type u_3}
(f : α → β)
(g : β → Option γ)
(l : List α)
:
List.filterMap g (List.map f l) = List.filterMap (g ∘ f) l
theorem
List.filter_filterMap
{α : Type u_1}
{β : Type u_2}
(f : α → Option β)
(p : β → Bool)
(l : List α)
:
List.filter p (List.filterMap f l) = List.filterMap (fun (x : α) => Option.filter p (f x)) l
theorem
List.filterMap_filter
{α : Type u_1}
{β : Type u_2}
(p : α → Bool)
(f : α → Option β)
(l : List α)
:
List.filterMap f (List.filter p l) = List.filterMap (fun (x : α) => if p x = true then f x else none) l
theorem
List.map_filterMap_some_eq_filter_map_is_some
{α : Type u_1}
{β : Type u_2}
(f : α → Option β)
(l : List α)
:
List.map some (List.filterMap f l) = List.filter (fun (b : Option β) => b.isSome) (List.map f l)
@[simp]
theorem
List.filterMap_join
{α : Type u_1}
{β : Type u_2}
(f : α → Option β)
(L : List (List α))
:
List.filterMap f L.join = (List.map (List.filterMap f) L).join
theorem
List.map_filterMap_of_inv
{α : Type u_1}
{β : Type u_2}
(f : α → Option β)
(g : β → α)
(H : ∀ (x : α), Option.map g (f x) = some x)
(l : List α)
:
List.map g (List.filterMap f l) = l
theorem
List.map_filter
{β : Type u_1}
{α : Type u_2}
{p : α → Bool}
(f : β → α)
(l : List β)
:
List.filter p (List.map f l) = List.map f (List.filter (p ∘ f) l)
@[simp]
theorem
List.filter_filter :
∀ {α : Type u_1} {p : α → Bool} (q : α → Bool) (l : List α),
List.filter p (List.filter q l) = List.filter (fun (a : α) => decide (p a = true ∧ q a = true)) l
find? #
theorem
List.find?_cons_of_neg :
∀ {α : Type u_1} {p : α → Bool} {a : α} (l : List α), ¬p a = true → List.find? p (a :: l) = List.find? p l
@[simp]
findSome? #
takeWhile and dropWhile #
@[simp]
theorem
List.takeWhile_append_dropWhile
{α : Type u_1}
(p : α → Bool)
(l : List α)
:
List.takeWhile p l ++ List.dropWhile p l = l
theorem
List.dropWhile_append
{α : Type u_1}
{p : α → Bool}
{xs : List α}
{ys : List α}
:
List.dropWhile p (xs ++ ys) = if (List.dropWhile p xs).isEmpty = true then List.dropWhile p ys else List.dropWhile p xs ++ ys
enum, enumFrom #
@[simp]
theorem
List.enumFrom_length
{α : Type u_1}
{n : Nat}
{l : List α}
:
(List.enumFrom n l).length = l.length
maximum? #
theorem
List.maximum?_cons
{α : Type u_1}
{x : α}
[Max α]
{xs : List α}
:
(x :: xs).maximum? = some (List.foldl max x xs)