Bootstrapping theorems for lists #
These are theorems used in the definitions of Std.Data.List.Basic
and tactics.
New theorems should be added to Std.Data.List.Lemmas
if they are not needed by the bootstrap.
@[simp]
@[simp]
@[simp]
@[simp]
theorem
List.tailD_cons
{α : Type u_1}
{a : α}
{l : List α}
{l' : List α}
:
List.tailD (a :: l) l' = l
length #
mem #
append #
theorem
List.append_inj_right :
∀ {α : Type u_1} {s₁ t₁ s₂ t₂ : List α}, s₁ ++ t₁ = s₂ ++ t₂ → List.length s₁ = List.length s₂ → t₁ = t₂
theorem
List.append_inj_left :
∀ {α : Type u_1} {s₁ t₁ s₂ t₂ : List α}, s₁ ++ t₁ = s₂ ++ t₂ → List.length s₁ = List.length s₂ → s₁ = s₂
theorem
List.append_inj_right' :
∀ {α : Type u_1} {s₁ t₁ s₂ t₂ : List α}, s₁ ++ t₁ = s₂ ++ t₂ → List.length t₁ = List.length t₂ → t₁ = t₂
theorem
List.append_inj_left' :
∀ {α : Type u_1} {s₁ t₁ s₂ t₂ : List α}, s₁ ++ t₁ = s₂ ++ t₂ → List.length t₁ = List.length t₂ → s₁ = s₂
map #
bind #
join #
bounded quantifiers over Lists #
reverse #
@[simp]
theorem
List.reverseAux_cons :
∀ {α : Type u_1} {a : α} {l r : List α}, List.reverseAux (a :: l) r = List.reverseAux l (a :: r)
theorem
List.reverseAux_eq
{α : Type u_1}
(as : List α)
(bs : List α)
:
List.reverseAux as bs = List.reverse as ++ bs
theorem
List.reverse_map
{α : Type u_1}
{β : Type u_2}
(f : α → β)
(l : List α)
:
List.reverse (List.map f l) = List.map f (List.reverse l)
@[simp]
nth element #
theorem
List.get_of_mem
{α : Type u_1}
{a : α}
{l : List α}
:
a ∈ l → ∃ (n : Fin (List.length l)), List.get l n = a
theorem
List.get?_len_le
{α : Type u_1}
{l : List α}
{n : Nat}
:
List.length l ≤ n → List.get? l n = none
@[simp]
@[simp]
theorem
List.get?_concat_length
{α : Type u_1}
(l : List α)
(a : α)
:
List.get? (l ++ [a]) (List.length l) = some a
theorem
List.getLast_eq_get
{α : Type u_1}
(l : List α)
(h : l ≠ [])
:
List.getLast l h = List.get l { val := List.length l - 1, isLt := ⋯ }
theorem
List.getLast?_eq_getLast
{α : Type u_1}
(l : List α)
(h : l ≠ [])
:
List.getLast? l = some (List.getLast l h)
theorem
List.getLast?_eq_get?
{α : Type u_1}
(l : List α)
:
List.getLast? l = List.get? l (List.length l - 1)
@[simp]
theorem
List.getD_eq_get?
{α : Type u_1}
(l : List α)
(n : Nat)
(a : α)
:
List.getD l n a = Option.getD (List.get? l n) a
theorem
List.get?_append_right
{α : Type u_1}
{l₁ : List α}
{l₂ : List α}
{n : Nat}
:
List.length l₁ ≤ n → List.get? (l₁ ++ l₂) n = List.get? l₂ (n - List.length l₁)
theorem
List.get?_reverse'
{α : Type u_1}
{l : List α}
(i : Nat)
(j : Nat)
:
i + j + 1 = List.length l → List.get? (List.reverse l) i = List.get? l j
theorem
List.get?_reverse
{α : Type u_1}
{l : List α}
(i : Nat)
(h : i < List.length l)
:
List.get? (List.reverse l) i = List.get? l (List.length l - 1 - i)
take and drop #
@[simp]
theorem
List.length_drop
{α : Type u_1}
(i : Nat)
(l : List α)
:
List.length (List.drop i l) = List.length l - i
@[simp]
theorem
List.take_concat_get
{α : Type u_1}
(l : List α)
(i : Nat)
(h : i < List.length l)
:
List.concat (List.take i l) l[i] = List.take (i + 1) l
theorem
List.reverse_concat
{α : Type u_1}
(l : List α)
(a : α)
:
List.reverse (List.concat l a) = a :: List.reverse l
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 (List.reverse l) = 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 (List.reverse l) = 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 (List.reverse l) = 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 (List.reverse l) = 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'
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 (List.reverse acc ++ __do_lift)
forM #
eraseIdx #
@[simp]
theorem
List.eraseIdx_cons_zero :
∀ {α : Type u_1} {a : α} {as : List α}, List.eraseIdx (a :: as) 0 = as
@[simp]
theorem
List.eraseIdx_cons_succ :
∀ {α : Type u_1} {a : α} {as : List α} {i : Nat}, List.eraseIdx (a :: as) (i + 1) = a :: List.eraseIdx as i
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 #
@[simp]
theorem
List.replace_cons
{α : Type u_1}
{as : List α}
{b : α}
{c : α}
[BEq α]
{a : α}
:
List.replace (a :: as) b c = match a == b with
| true => c :: as
| false => a :: List.replace as b c
@[simp]
theorem
List.replace_cons_self
{α : Type u_1}
{as : List α}
{b : α}
[BEq α]
[LawfulBEq α]
{a : α}
:
List.replace (a :: as) a b = b :: as
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 #
@[simp]
theorem
List.unzip_cons
{α : Type u_1}
{β : Type u_2}
{t : List (α × β)}
{h : α × β}
:
List.unzip (h :: t) = match List.unzip t with
| (al, bl) => (h.fst :: al, h.snd :: bl)
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 #
@[simp]
@[simp]
theorem
List.isPrefixOf_cons_nil
{α : Type u_1}
{a : α}
{as : List α}
[BEq α]
:
List.isPrefixOf (a :: as) [] = false
theorem
List.isPrefixOf_cons₂
{α : Type u_1}
{as : List α}
{b : α}
{bs : List α}
[BEq α]
{a : α}
:
List.isPrefixOf (a :: as) (b :: bs) = (a == b && List.isPrefixOf as bs)
@[simp]
theorem
List.isPrefixOf_cons₂_self
{α : Type u_1}
{as : List α}
{bs : List α}
[BEq α]
[LawfulBEq α]
{a : α}
:
List.isPrefixOf (a :: as) (a :: bs) = List.isPrefixOf as bs
isEqv #
@[simp]
@[simp]
theorem
List.isEqv_nil_cons
{α : Type u_1}
{a : α}
{as : List α}
{eqv : α → α → Bool}
:
List.isEqv [] (a :: as) eqv = false
@[simp]
theorem
List.isEqv_cons_nil
{α : Type u_1}
{a : α}
{as : List α}
{eqv : α → α → Bool}
:
List.isEqv (a :: as) [] eqv = false
theorem
List.isEqv_cons₂ :
∀ {α : Type u_1} {a : α} {as : List α} {b : α} {bs : List α} {eqv : α → α → Bool},
List.isEqv (a :: as) (b :: bs) eqv = (eqv a b && List.isEqv as bs eqv)
dropLast #
@[simp]
theorem
List.dropLast_cons₂ :
∀ {α : Type u_1} {x y : α} {zs : List α}, List.dropLast (x :: y :: zs) = x :: List.dropLast (y :: zs)
minimum? #
theorem
List.minimum?_cons
{α : Type u_1}
{x : α}
[Min α]
{xs : List α}
:
List.minimum? (x :: xs) = some (List.foldl min x xs)
@[simp]
theorem
List.minimum?_eq_none_iff
{α : Type u_1}
{xs : List α}
[Min α]
:
List.minimum? xs = none ↔ xs = []