Basic properties of lists #
There is only one list of an empty type
Equations
- list.unique_of_is_empty = {to_inhabited := {default := default (list.inhabited α)}, uniq := _}
mem #
If each element of a list can be lifted to some type, then the whole list can be lifted to this type.
Equations
- list.can_lift = {coe := list.map can_lift.coe, cond := λ (l : list α), ∀ (x : α), x ∈ l → can_lift.cond β x, prf := _}
length #
set-theoretic notation of lists #
bounded quantifiers over lists #
list subset #
append #
repeat #
pure #
bind #
concat #
reverse #
empty #
init #
last #
last' #
head(') and tail #
Induction from the right #
Induction principle from the right for lists: if a property holds for the empty list, and
for l ++ [a]
if it holds for l
, then it holds for all lists. The principle is given for
a Sort
-valued predicate, i.e., it can also be used to construct data.
Bidirectional induction principle for lists: if a property holds for the empty list, the
singleton list, and a :: (l ++ [b])
from l
, then it holds for all lists. This can be used to
prove statements about palindromes. The principle is given for a Sort
-valued predicate, i.e., it
can also be used to construct data.
Equations
- list.bidirectional_rec H0 H1 Hn (a :: b :: l) = let l' : list α := (b :: l).init, b' : α := (b :: l).last _ in _.mpr (Hn a l' b' (list.bidirectional_rec H0 H1 Hn l'))
- list.bidirectional_rec H0 H1 Hn [a] = H1 a
- list.bidirectional_rec H0 H1 Hn list.nil = H0
Like bidirectional_rec
, but with the list parameter placed first.
Equations
- l.bidirectional_rec_on H0 H1 Hn = list.bidirectional_rec H0 H1 Hn l
sublists #
Equations
- (a :: l₁).decidable_sublist (b :: l₂) = dite (a = b) (λ (h : a = b), decidable_of_decidable_of_iff (l₁.decidable_sublist l₂) _) (λ (h : ¬a = b), decidable_of_decidable_of_iff ((a :: l₁).decidable_sublist l₂) _)
- (a :: l₁).decidable_sublist list.nil = is_false _
- list.nil.decidable_sublist (hd :: tl) = is_true _
- list.nil.decidable_sublist list.nil = is_true list.decidable_sublist._main._proof_1
index_of #
nth element #
If one has nth_le 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 lemma nth_le_of_eq
can be used to make
such a rewrite, with rw (nth_le_of_eq h)
.
map #
A single list.map
of a composition of functions is equal to
composing a list.map
with another list.map
, fully applied.
This is the reverse direction of list.map_map
.
map₂ #
take, drop #
Dropping the elements up to n
in l₁ ++ l₂
is the same as dropping the elements up to n
in l₁
, dropping the elements up to n - l₁.length
in l₂
, and appending them.
foldl, foldr #
Induction principle for values produced by a foldr
: if a property holds
for the seed element b : β
and for all incremental op : α → β → β
performed on the elements (a : α) ∈ l
. The principle is given for
a Sort
-valued predicate, i.e., it can also be used to construct data.
Equations
- l.foldr_rec_on op b hb hl = list.rec (λ (hl : Π (b : β), C b → Π (a : α), a ∈ list.nil → C (op a b)), hb) (λ (hd : α) (tl : list α) (IH : (Π (b : β), C b → Π (a : α), a ∈ tl → C (op a b)) → C (list.foldr op b tl)) (hl : Π (b : β), C b → Π (a : α), a ∈ hd :: tl → C (op a b)), hl (list.foldr op b tl) (IH (λ (y : β) (hy : C y) (x : α) (hx : x ∈ tl), hl y hy x _)) hd _) l hl
Induction principle for values produced by a foldl
: if a property holds
for the seed element b : β
and for all incremental op : β → α → β
performed on the elements (a : α) ∈ l
. The principle is given for
a Sort
-valued predicate, i.e., it can also be used to construct data.
Equations
- l.foldl_rec_on op b hb hl = list.rec (λ (hl : Π (b : β), C b → Π (a : α), a ∈ list.nil → C (op b a)) (b : β) (hb : C b), hb) (λ (hd : α) (tl : list α) (IH : (Π (b : β), C b → Π (a : α), a ∈ tl → C (op b a)) → Π (b : β), C b → C (list.foldl op b tl)) (hl : Π (b : β), C b → Π (a : α), a ∈ hd :: tl → C (op b a)) (b : β) (hb : C b), IH (λ (y : β) (hy : C y) (x : α) (hx : x ∈ tl), hl y hy x _) (op b hd) (hl b hb hd _)) l hl b hb
mfoldl, mfoldr, mmap #
intersperse #
split_at and split_on #
An auxiliary definition for proving a specification lemma for split_on_p
.
split_on_p_aux' P xs ys
splits the list ys ++ xs
at every element satisfying P
,
where ys
is an accumulating parameter for the initial segment of elements not satisfying P
.
Equations
- list.split_on_p_aux' P (h :: t) xs = ite (P h) (xs :: list.split_on_p_aux' P t list.nil) (list.split_on_p_aux' P t (xs ++ [h]))
- list.split_on_p_aux' P list.nil xs = [xs]
The original list L
can be recovered by joining the lists produced by split_on_p p L
,
interspersed with the elements L.filter p
.
If no element satisfies p
in the list xs
, then xs.split_on_p p = [xs]
When a list of the form [...xs, sep, ...as]
is split on p
, the first element is xs
,
assuming no element in xs
satisfies p
but sep
does satisfy p
intercalate [x]
is the left inverse of split_on x
split_on x
is the left inverse of intercalate [x]
, on the domain
consisting of each nonempty list of lists ls
whose elements do not contain x
map for partial functions #
Partial map. If f : Π a, p a → β
is a partial function defined on
a : α
satisfying p
, then pmap f l h
is essentially the same as map f l
but is defined only when all members of l
satisfy p
, using the proof
to apply f
.
"Attach" the proof that the elements of l
are in l
to produce a new list
with the same elements but in the type {x // x ∈ l}
.
Equations
- l.attach = list.pmap subtype.mk l _
find #
lookmap #
filter_map #
reduce_option #
filter #
erasep #
erase #
diff #
enum #
map₂_left' #
map₂_right' #
zip_left' #
zip_right' #
map₂_left #
map₂_right #
zip_left #
zip_right #
to_chunks #
all₂ #
Equations
- list.all₂.decidable_pred p = λ (l : list α), decidable_of_iff' (∀ (x : α), x ∈ l → p x) list.all₂_iff_forall
Retroattributes #
The list definitions happen earlier than to_additive
, so here we tag the few multiplicative
definitions that couldn't be tagged earlier.