Basic properties of lists #
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
.
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 #
prefix, suffix, infix #
Equations
- (hd :: tl).decidable_suffix (hd_1 :: tl_1) = let len1 : ℕ := (hd :: tl).length, len2 : ℕ := (hd_1 :: tl_1).length in dite (len1 ≤ len2) (λ (hl : len1 ≤ len2), decidable_of_iff' (hd :: tl = list.drop (len2 - len1) (hd_1 :: tl_1)) _) (λ (hl : ¬len1 ≤ len2), is_false _)
- (a :: l₁).decidable_suffix list.nil = is_false _
- list.nil.decidable_suffix l₂ = is_true _
Equations
- (hd :: tl).decidable_infix (hd_1 :: tl_1) = decidable_of_decidable_of_iff (list.decidable_bex (λ (t : list α), hd :: tl <+: t) (hd_1 :: tl_1).tails) _
- (a :: l₁).decidable_infix list.nil = is_false _
- list.nil.decidable_infix l₂ = is_true _
insert #
erasep #
erase #
diff #
enum #
map₂_left' #
map₂_right' #
zip_left' #
zip_right' #
map₂_left #
map₂_right #
zip_left #
zip_right #
to_chunks #
Retroattributes #
The list definitions happen earlier than to_additive
, so here we tag the few multiplicative
definitions that couldn't be tagged earlier.