Library HoTT.Spaces.List.Theory
Require Import Basics.Overture Basics.Tactics Basics.PathGroupoids Basics.Trunc
Basics.Equivalences Basics.Decidable Basics.Iff.
Require Import Types.Paths Types.Unit Types.Prod Types.Sigma Types.Sum
Types.Empty Types.Option.
Require Export Spaces.List.Core Spaces.Nat.Core.
Local Set Universe Minimization ToSet.
Local Set Polymorphic Inductive Cumulativity.
Basics.Equivalences Basics.Decidable Basics.Iff.
Require Import Types.Paths Types.Unit Types.Prod Types.Sigma Types.Sum
Types.Empty Types.Option.
Require Export Spaces.List.Core Spaces.Nat.Core.
Local Set Universe Minimization ToSet.
Local Set Polymorphic Inductive Cumulativity.
Theory of Lists and List Operations
Local Open Scope list_scope.
Definition length_0 {A : Type} (l : list A) (H : length l = 0%nat)
: l = nil.
Proof.
destruct l.
- reflexivity.
- discriminate.
Defined.
: l = nil.
Proof.
destruct l.
- reflexivity.
- discriminate.
Defined.
Definition app_nil {A : Type} (l : list A)
: l ++ nil = l.
Proof.
induction l as [|a l IHl].
1: reflexivity.
simpl; f_ap.
Defined.
: l ++ nil = l.
Proof.
induction l as [|a l IHl].
1: reflexivity.
simpl; f_ap.
Defined.
Associativity of list concatenation.
Definition app_assoc {A : Type} (x y z : list A)
: app x (app y z) = app (app x y) z.
Proof.
induction x as [|a x IHx] in |- ×.
- reflexivity.
- exact (ap (cons a) IHx).
Defined.
: app x (app y z) = app (app x y) z.
Proof.
induction x as [|a x IHx] in |- ×.
- reflexivity.
- exact (ap (cons a) IHx).
Defined.
The type of lists has a monoidal structure given by concatenation.
Definition list_pentagon {A : Type} (w x y z : list A)
: app_assoc w x (y ++ z) @ app_assoc (w ++ x) y z
= ap (fun l ⇒ w ++ l) (app_assoc x y z)
@ app_assoc w (x ++ y) z
@ ap (fun l ⇒ l ++ z) (app_assoc w x y).
Proof.
symmetry.
induction w as [|? w IHw] in x, y, z |- ×.
- simpl.
apply equiv_p1_1q.
lhs nrapply concat_p1.
apply ap_idmap.
- simpl.
rhs_V nrapply ap_pp.
rhs_V nrapply (ap (ap (cons a)) (IHw x y z)).
rhs nrapply ap_pp.
f_ap.
{ rhs nrapply ap_pp.
f_ap.
apply ap_compose. }
lhs_V nrapply ap_compose.
nrapply (ap_compose (fun l ⇒ l ++ z)).
Defined.
: app_assoc w x (y ++ z) @ app_assoc (w ++ x) y z
= ap (fun l ⇒ w ++ l) (app_assoc x y z)
@ app_assoc w (x ++ y) z
@ ap (fun l ⇒ l ++ z) (app_assoc w x y).
Proof.
symmetry.
induction w as [|? w IHw] in x, y, z |- ×.
- simpl.
apply equiv_p1_1q.
lhs nrapply concat_p1.
apply ap_idmap.
- simpl.
rhs_V nrapply ap_pp.
rhs_V nrapply (ap (ap (cons a)) (IHw x y z)).
rhs nrapply ap_pp.
f_ap.
{ rhs nrapply ap_pp.
f_ap.
apply ap_compose. }
lhs_V nrapply ap_compose.
nrapply (ap_compose (fun l ⇒ l ++ z)).
Defined.
The length of a concatenated list is the sum of the lengths of the two lists.
Definition length_app {A : Type} (l l' : list A)
: length (l ++ l') = (length l + length l')%nat.
Proof.
induction l as [|a l IHl] using list_ind.
1: reflexivity.
simpl.
exact (ap S IHl).
Defined.
: length (l ++ l') = (length l + length l')%nat.
Proof.
induction l as [|a l IHl] using list_ind.
1: reflexivity.
simpl.
exact (ap S IHl).
Defined.
An element of a concatenated list is equivalently either in the first list or in the second list.
Definition equiv_inlist_app {A : Type} (l l' : list A) (x : A)
: InList x l + InList x l' <~> InList x (l ++ l').
Proof.
induction l as [|a l IHl].
- apply sum_empty_l.
- cbn; nrefine (_ oE equiv_sum_assoc _ _ _).
by apply equiv_functor_sum_l.
Defined.
: InList x l + InList x l' <~> InList x (l ++ l').
Proof.
induction l as [|a l IHl].
- apply sum_empty_l.
- cbn; nrefine (_ oE equiv_sum_assoc _ _ _).
by apply equiv_functor_sum_l.
Defined.
Folding
Lemma fold_left_app {A B : Type} (f : A → B → A) (l l' : list B) (i : A)
: fold_left f (l ++ l') i = fold_left f l' (fold_left f l i).
Proof.
induction l in i |- ×.
1: reflexivity.
apply IHl.
Defined.
: fold_left f (l ++ l') i = fold_left f l' (fold_left f l i).
Proof.
induction l in i |- ×.
1: reflexivity.
apply IHl.
Defined.
A right fold over a concatenated list is equivalent to folding over the second followed by folding over the first.
Lemma fold_right_app {A B : Type} (f : B → A → A) (i : A) (l l' : list B)
: fold_right f i (l ++ l') = fold_right f (fold_right f i l') l.
Proof.
induction l in i |- ×.
1: reflexivity.
exact (ap (f a) (IHl _)).
Defined.
: fold_right f i (l ++ l') = fold_right f (fold_right f i l') l.
Proof.
induction l in i |- ×.
1: reflexivity.
exact (ap (f a) (IHl _)).
Defined.
Definition length_list_map {A B : Type} (f : A → B) (l : list A)
: length (list_map f l) = length l.
Proof.
induction l as [|x l IHl] using list_ind.
- reflexivity.
- simpl.
exact (ap S IHl).
Defined.
: length (list_map f l) = length l.
Proof.
induction l as [|x l IHl] using list_ind.
- reflexivity.
- simpl.
exact (ap S IHl).
Defined.
A function applied to an element of a list is an element of the mapped list.
Definition inlist_map {A B : Type} (f : A → B) (l : list A) (x : A)
: InList x l → InList (f x) (list_map f l).
Proof.
simple_list_induction l y l IHl.
1: contradiction.
intros [p | i].
- left. exact (ap f p).
- right. exact (IHl i).
Defined.
: InList x l → InList (f x) (list_map f l).
Proof.
simple_list_induction l y l IHl.
1: contradiction.
intros [p | i].
- left. exact (ap f p).
- right. exact (IHl i).
Defined.
An element of a mapped list is equal to the function applied to some element of the original list.
Definition inlist_map' {A B : Type} (f : A → B) (l : list A) (x : B)
: InList x (list_map f l) → { y : A & (f y = x) × InList y l }.
Proof.
induction l as [|y l IHl].
1: contradiction.
intros [p | i].
- exact (y; (p, inl idpath)).
- destruct (IHl i) as [y' [p i']].
exact (y'; (p, inr i')).
Defined.
: InList x (list_map f l) → { y : A & (f y = x) × InList y l }.
Proof.
induction l as [|y l IHl].
1: contradiction.
intros [p | i].
- exact (y; (p, inl idpath)).
- destruct (IHl i) as [y' [p i']].
exact (y'; (p, inr i')).
Defined.
Mapping a function over a concatenated list is the concatenation of the mapped lists.
Definition list_map_app {A B : Type} (f : A → B) (l l' : list A)
: list_map f (l ++ l') = list_map f l ++ list_map f l'.
Proof.
induction l as [|a l IHl].
1: reflexivity.
simpl; f_ap.
Defined.
: list_map f (l ++ l') = list_map f l ++ list_map f l'.
Proof.
induction l as [|a l IHl].
1: reflexivity.
simpl; f_ap.
Defined.
A function that acts as the identity on the elements of a list is the identity on the mapped list.
Lemma list_map_id {A : Type} (f : A → A) (l : list A)
(Hf : ∀ x, InList x l → f x = x)
: list_map f l = l.
Proof.
induction l as [|x l IHl].
- reflexivity.
- simpl.
nrapply ap011.
+ exact (Hf _ (inl idpath)).
+ apply IHl.
intros y Hy.
apply Hf.
by right.
Defined.
(Hf : ∀ x, InList x l → f x = x)
: list_map f l = l.
Proof.
induction l as [|x l IHl].
- reflexivity.
- simpl.
nrapply ap011.
+ exact (Hf _ (inl idpath)).
+ apply IHl.
intros y Hy.
apply Hf.
by right.
Defined.
A list_map of a composition is the composition of the maps.
Definition list_map_compose {A B C} (f : A → B) (g : B → C) (l : list A)
: list_map (fun x ⇒ g (f x)) l = list_map g (list_map f l).
Proof.
induction l as [|a l IHl].
1: reflexivity.
simpl; f_ap.
Defined.
: list_map (fun x ⇒ g (f x)) l = list_map g (list_map f l).
Proof.
induction l as [|a l IHl].
1: reflexivity.
simpl; f_ap.
Defined.
TODO: generalize as max The length of a list_map2 is the same as the length of the original lists.
Definition length_list_map2@{i j k|} {A : Type@{i}} {B : Type@{j}} {C : Type@{k}}
(f : A → B → C) defl defr l1 l2
: length l1 = length l2
→ length (list_map2 f defl defr l1 l2) = length l1.
Proof.
intros p.
induction l1 as [|x l1 IHl1] in l2, p |- × using list_ind@{i j}.
- destruct l2.
+ reflexivity.
+ inversion p.
- destruct l2.
+ inversion p.
+ cbn; f_ap.
by apply IHl1, path_nat_succ.
Defined.
(f : A → B → C) defl defr l1 l2
: length l1 = length l2
→ length (list_map2 f defl defr l1 l2) = length l1.
Proof.
intros p.
induction l1 as [|x l1 IHl1] in l2, p |- × using list_ind@{i j}.
- destruct l2.
+ reflexivity.
+ inversion p.
- destruct l2.
+ inversion p.
+ cbn; f_ap.
by apply IHl1, path_nat_succ.
Defined.
An element of a list_map2 is the result of applying the function to some elements of the original lists.
Definition inlist_map2@{i j k u | i ≤ u, j ≤ u, k ≤ u}
{A : Type@{i}} {B : Type@{j}} {C : Type@{k}}
(f : A → B → C) defl defr l1 l2 x
: InList x (list_map2 f defl defr l1 l2) → length l1 = length l2
→ { y : A & { z : B &
prod@{k u} ((f y z) = x) (InList y l1 × InList z l2) } }.
Proof.
intros H p.
induction l1 as [|y l1 IHl1] in l2, x, H, p |- × using list_ind@{i u}.
- destruct l2.
1: contradiction.
inversion p.
- destruct l2 as [| z].
1: inversion p.
destruct H as [q | i].
1: exact (y; z; (q, (inl idpath, inl idpath))).
destruct (IHl1 l2 x i) as [y' [z' [q [r s]]]].
1: apply path_nat_succ, p.
exact (y'; z'; (q, (inr r, inr s))).
Defined.
{A : Type@{i}} {B : Type@{j}} {C : Type@{k}}
(f : A → B → C) defl defr l1 l2 x
: InList x (list_map2 f defl defr l1 l2) → length l1 = length l2
→ { y : A & { z : B &
prod@{k u} ((f y z) = x) (InList y l1 × InList z l2) } }.
Proof.
intros H p.
induction l1 as [|y l1 IHl1] in l2, x, H, p |- × using list_ind@{i u}.
- destruct l2.
1: contradiction.
inversion p.
- destruct l2 as [| z].
1: inversion p.
destruct H as [q | i].
1: exact (y; z; (q, (inl idpath, inl idpath))).
destruct (IHl1 l2 x i) as [y' [z' [q [r s]]]].
1: apply path_nat_succ, p.
exact (y'; z'; (q, (inr r, inr s))).
Defined.
Definition list_map2_repeat_l {A B C} (f : A → B → C) (x : A) l {defl defr}
: list_map2 f defl defr (repeat x (length l)) l = list_map (f x) l.
Proof.
induction l as [|y l IHl].
- reflexivity.
- cbn; f_ap.
Defined.
: list_map2 f defl defr (repeat x (length l)) l = list_map (f x) l.
Proof.
induction l as [|y l IHl].
- reflexivity.
- cbn; f_ap.
Defined.
Definition list_map2_repeat_r {A B C} (f : A → B → C) (y : B) l {defl defr}
: list_map2 f defl defr l (repeat y (length l)) = list_map (fun x ⇒ f x y) l.
Proof.
induction l as [|x l IHl].
- reflexivity.
- cbn; f_ap.
Defined.
: list_map2 f defl defr l (repeat y (length l)) = list_map (fun x ⇒ f x y) l.
Proof.
induction l as [|x l IHl].
- reflexivity.
- cbn; f_ap.
Defined.
Definition length_reverse_acc@{i|} {A : Type@{i}} (acc l : list A)
: length (reverse_acc acc l) = (length acc + length l)%nat.
Proof.
symmetry.
induction l as [|x l IHl] in acc |- × using list_ind@{i i}.
- apply nat_add_zero_r.
- rhs_V nrapply IHl.
apply nat_add_succ_r.
Defined.
: length (reverse_acc acc l) = (length acc + length l)%nat.
Proof.
symmetry.
induction l as [|x l IHl] in acc |- × using list_ind@{i i}.
- apply nat_add_zero_r.
- rhs_V nrapply IHl.
apply nat_add_succ_r.
Defined.
The length of reverse is the same as the length of the original list.
Definition length_reverse {A : Type} (l : list A)
: length (reverse l) = length l.
Proof.
rapply length_reverse_acc.
Defined.
: length (reverse l) = length l.
Proof.
rapply length_reverse_acc.
Defined.
Definition list_map_reverse_acc {A B : Type}
(f : A → B) (l l' : list A)
: list_map f (reverse_acc l' l) = reverse_acc (list_map f l') (list_map f l).
Proof.
revert l'; simple_list_induction l a l IHl; intro l'.
1: reflexivity.
apply IHl.
Defined.
(f : A → B) (l l' : list A)
: list_map f (reverse_acc l' l) = reverse_acc (list_map f l') (list_map f l).
Proof.
revert l'; simple_list_induction l a l IHl; intro l'.
1: reflexivity.
apply IHl.
Defined.
Definition list_map_reverse {A B} (f : A → B) (l : list A)
: list_map f (reverse l) = reverse (list_map f l).
Proof.
nrapply list_map_reverse_acc.
Defined.
: list_map f (reverse l) = reverse (list_map f l).
Proof.
nrapply list_map_reverse_acc.
Defined.
reverse_acc is the same as concatenating the reversed list with the accumulator.
Definition reverse_acc_cons {A : Type} (l l' : list A)
: reverse_acc l' l = reverse l ++ l'.
Proof.
induction l as [|a l IHl] in l' |- ×.
1: reflexivity.
lhs nrapply IHl.
lhs nrapply (app_assoc _ [a]).
f_ap; symmetry.
apply IHl.
Defined.
: reverse_acc l' l = reverse l ++ l'.
Proof.
induction l as [|a l IHl] in l' |- ×.
1: reflexivity.
lhs nrapply IHl.
lhs nrapply (app_assoc _ [a]).
f_ap; symmetry.
apply IHl.
Defined.
Definition reverse_cons {A : Type} (a : A) (l : list A)
: reverse (a :: l) = reverse l ++ [a].
Proof.
induction l as [|b l IHl] in a |- ×.
1: reflexivity.
rewrite IHl.
rewrite <- app_assoc.
cbn; apply reverse_acc_cons.
Defined.
: reverse (a :: l) = reverse l ++ [a].
Proof.
induction l as [|b l IHl] in a |- ×.
1: reflexivity.
rewrite IHl.
rewrite <- app_assoc.
cbn; apply reverse_acc_cons.
Defined.
The reverse of a concatenated list is the concatenation of the reversed lists in reverse order.
Definition reverse_app {A : Type} (l l' : list A)
: reverse (l ++ l') = reverse l' ++ reverse l.
Proof.
induction l as [|a l IHl] in l' |- ×.
1: symmetry; apply app_nil.
simpl.
lhs nrapply reverse_cons.
rhs nrapply ap.
2: nrapply reverse_cons.
rhs nrapply app_assoc.
nrapply (ap (fun l ⇒ l ++ [a])).
exact (IHl l').
Defined.
: reverse (l ++ l') = reverse l' ++ reverse l.
Proof.
induction l as [|a l IHl] in l' |- ×.
1: symmetry; apply app_nil.
simpl.
lhs nrapply reverse_cons.
rhs nrapply ap.
2: nrapply reverse_cons.
rhs nrapply app_assoc.
nrapply (ap (fun l ⇒ l ++ [a])).
exact (IHl l').
Defined.
reverse is involutive.
Definition reverse_reverse {A : Type} (l : list A)
: reverse (reverse l) = l.
Proof.
induction l.
1: reflexivity.
lhs nrapply ap.
1: nrapply reverse_cons.
lhs nrapply reverse_app.
exact (ap _ IHl).
Defined.
: reverse (reverse l) = l.
Proof.
induction l.
1: reflexivity.
lhs nrapply ap.
1: nrapply reverse_cons.
lhs nrapply reverse_app.
exact (ap _ IHl).
Defined.
Getting elements
Definition nth_lt@{i|} {A : Type@{i}} (l : list A) (n : nat)
(H : (n < length l)%nat)
: { x : A & nth l n = Some x }.
Proof.
induction l as [|a l IHa] in n, H |- × using list_ind@{i i}.
1: destruct (not_lt_zero_r _ H).
destruct n.
1: by ∃ a.
apply IHa.
apply leq_pred'.
exact H.
Defined.
(H : (n < length l)%nat)
: { x : A & nth l n = Some x }.
Proof.
induction l as [|a l IHa] in n, H |- × using list_ind@{i i}.
1: destruct (not_lt_zero_r _ H).
destruct n.
1: by ∃ a.
apply IHa.
apply leq_pred'.
exact H.
Defined.
A variant of nth that always returns an element when we know that the index is in the list.
Definition nth' {A : Type} (l : list A) (n : nat) (H : (n < length l)%nat) : A
:= pr1 (nth_lt l n H).
:= pr1 (nth_lt l n H).
Definition nth'_nth' {A} (l : list A) (n : nat) (H H' : (n < length l)%nat)
: nth' l n H = nth' l n H'.
Proof.
apply ap, path_ishprop.
Defined.
: nth' l n H = nth' l n H'.
Proof.
apply ap, path_ishprop.
Defined.
The nth' element of a list is in the list.
Definition inlist_nth'@{i|} {A : Type@{i}} (l : list A) (n : nat)
(H : (n < length l)%nat)
: InList (nth' l n H) l.
Proof.
induction l as [|a l IHa] in n, H |- × using list_ind@{i i}.
1: destruct (not_lt_zero_r _ H).
destruct n.
1: by left.
right.
apply IHa.
Defined.
(H : (n < length l)%nat)
: InList (nth' l n H) l.
Proof.
induction l as [|a l IHa] in n, H |- × using list_ind@{i i}.
1: destruct (not_lt_zero_r _ H).
destruct n.
1: by left.
right.
apply IHa.
Defined.
Definition nth_nth' {A} (l : list A) (n : nat) (H : (n < length l)%nat)
: nth l n = Some (nth' l n H).
Proof.
exact (nth_lt l n H).2.
Defined.
: nth l n = Some (nth' l n H).
Proof.
exact (nth_lt l n H).2.
Defined.
The nth' element of a cons indexed at n.+1 is the same as the nth' element of the tail indexed at n.
Definition nth'_cons {A : Type} (l : list A) (n : nat) (x : A)
(H : (n < length l)%nat) (H' : (n.+1 < length (x :: l))%nat)
: nth' (x :: l) n.+1 H' = nth' l n H.
Proof.
apply isinj_some.
nrefine (_^ @ _ @ _).
1,3: rapply nth_nth'.
reflexivity.
Defined.
(H : (n < length l)%nat) (H' : (n.+1 < length (x :: l))%nat)
: nth' (x :: l) n.+1 H' = nth' l n H.
Proof.
apply isinj_some.
nrefine (_^ @ _ @ _).
1,3: rapply nth_nth'.
reflexivity.
Defined.
The index of an element in a list is the n such that the nth' element is the element.
Definition index_of@{i|} {A : Type@{i}} (l : list A) (x : A)
: InList x l
→ sig@{Set i} (fun n : nat ⇒ { H : (n < length l)%nat & nth' l n H = x }).
Proof.
induction l as [|a l IHl] using list_ind@{i i}.
1: intros x'; destruct x'.
intros [| i].
- revert a p.
snrapply paths_ind_r@{i i}.
snrefine (exist@{i i} _ 0%nat _).
snrefine (exist _ _ idpath).
apply leq_succ.
exact _.
- destruct (IHl i) as [n [H H']].
snrefine (exist@{i i} _ n.+1%nat _).
snrefine (_; _); cbn.
1: apply leq_succ, H.
refine (_ @ H').
apply nth'_cons.
Defined.
: InList x l
→ sig@{Set i} (fun n : nat ⇒ { H : (n < length l)%nat & nth' l n H = x }).
Proof.
induction l as [|a l IHl] using list_ind@{i i}.
1: intros x'; destruct x'.
intros [| i].
- revert a p.
snrapply paths_ind_r@{i i}.
snrefine (exist@{i i} _ 0%nat _).
snrefine (exist _ _ idpath).
apply leq_succ.
exact _.
- destruct (IHl i) as [n [H H']].
snrefine (exist@{i i} _ n.+1%nat _).
snrefine (_; _); cbn.
1: apply leq_succ, H.
refine (_ @ H').
apply nth'_cons.
Defined.
The nth element of a map is the function applied optionally to the nth element of the original list.
Definition nth_list_map@{i j|} {A : Type@{i}} {B : Type@{j}}
(f : A → B) (l : list A) (n : nat)
: nth (list_map f l) n = functor_option f (nth l n).
Proof.
induction l as [|a l IHl] in n |- × using list_ind@{i j}.
1: by destruct n.
destruct n.
1: reflexivity.
apply IHl.
Defined.
(f : A → B) (l : list A) (n : nat)
: nth (list_map f l) n = functor_option f (nth l n).
Proof.
induction l as [|a l IHl] in n |- × using list_ind@{i j}.
1: by destruct n.
destruct n.
1: reflexivity.
apply IHl.
Defined.
Definition nth'_list_map@{i j|} {A : Type@{i}} {B : Type@{j}}
(f : A → B) (l : list A) (n : nat) (H : (n < length l)%nat)
(H' : (n < length (list_map f l))%nat)
: nth' (list_map f l) n H' = f (nth' l n H).
Proof.
induction l as [|a l IHl] in n, H, H' |- × using list_ind@{i j}.
1: destruct (not_lt_zero_r _ H).
destruct n.
1: reflexivity.
apply IHl.
Defined.
(f : A → B) (l : list A) (n : nat) (H : (n < length l)%nat)
(H' : (n < length (list_map f l))%nat)
: nth' (list_map f l) n H' = f (nth' l n H).
Proof.
induction l as [|a l IHl] in n, H, H' |- × using list_ind@{i j}.
1: destruct (not_lt_zero_r _ H).
destruct n.
1: reflexivity.
apply IHl.
Defined.
The nth' element of a list_map2 is the function applied to the nth' elements of the original lists. The length of the two lists is required to be the same.
Definition nth'_list_map2 {A B C : Type}
(f : A → B → C) (l1 : list A) (l2 : list B)
(n : nat) defl defr (H : (n < length l1)%nat) (H' : (n < length l2)%nat)
(H'' : (n < length (list_map2 f defl defr l1 l2))%nat)
(p : length l1 = length l2)
: f (nth' l1 n H) (nth' l2 n H') = nth' (list_map2 f defl defr l1 l2) n H''.
Proof.
revert l2 n defl defr H H' H'' p;
simple_list_induction l1 a l1 IHl1;
intros l2 n defl defr H H' H'' p.
- destruct l2 as [|b l2].
+ destruct (not_lt_zero_r _ H).
+ inversion p.
- destruct l2 as [|b l2].
+ inversion p.
+ destruct n.
× reflexivity.
× erewrite 3 nth'_cons.
apply IHl1.
by apply path_nat_succ.
Defined.
(f : A → B → C) (l1 : list A) (l2 : list B)
(n : nat) defl defr (H : (n < length l1)%nat) (H' : (n < length l2)%nat)
(H'' : (n < length (list_map2 f defl defr l1 l2))%nat)
(p : length l1 = length l2)
: f (nth' l1 n H) (nth' l2 n H') = nth' (list_map2 f defl defr l1 l2) n H''.
Proof.
revert l2 n defl defr H H' H'' p;
simple_list_induction l1 a l1 IHl1;
intros l2 n defl defr H H' H'' p.
- destruct l2 as [|b l2].
+ destruct (not_lt_zero_r _ H).
+ inversion p.
- destruct l2 as [|b l2].
+ inversion p.
+ destruct n.
× reflexivity.
× erewrite 3 nth'_cons.
apply IHl1.
by apply path_nat_succ.
Defined.
The nth' element of a repeat is the repeated value.
Definition nth'_repeat@{i|} {A : Type@{i}} (x : A) (i n : nat)
(H : (i < length (repeat x n))%nat)
: nth' (repeat x n) i H = x.
Proof.
induction n as [|n IHn] in i, H |- × using nat_ind@{i}.
1: destruct (not_lt_zero_r _ H).
destruct i.
1: reflexivity.
apply IHn.
Defined.
(H : (i < length (repeat x n))%nat)
: nth' (repeat x n) i H = x.
Proof.
induction n as [|n IHn] in i, H |- × using nat_ind@{i}.
1: destruct (not_lt_zero_r _ H).
destruct i.
1: reflexivity.
apply IHn.
Defined.
Two lists are equal if their nth' elements are equal.
Definition path_list_nth'@{i|} {A : Type@{i}} (l l' : list A)
(p : length l = length l')
: (∀ n (H : (n < length l)%nat), nth' l n H = nth' l' n (p # H))
→ l = l'.
Proof.
intros H.
induction l as [|a l IHl] in l', p, H |- × using list_ind@{i i}.
{ destruct l'.
- reflexivity.
- discriminate. }
destruct l' as [|a' l'].
1: discriminate.
f_ap.
- exact (H 0%nat _).
- snrapply IHl.
1: by apply path_nat_succ.
intros n Hn.
snrefine ((nth'_cons l n a Hn _)^ @ _).
1: apply leq_succ, Hn.
lhs nrapply H.
nrapply nth'_cons.
Defined.
(p : length l = length l')
: (∀ n (H : (n < length l)%nat), nth' l n H = nth' l' n (p # H))
→ l = l'.
Proof.
intros H.
induction l as [|a l IHl] in l', p, H |- × using list_ind@{i i}.
{ destruct l'.
- reflexivity.
- discriminate. }
destruct l' as [|a' l'].
1: discriminate.
f_ap.
- exact (H 0%nat _).
- snrapply IHl.
1: by apply path_nat_succ.
intros n Hn.
snrefine ((nth'_cons l n a Hn _)^ @ _).
1: apply leq_succ, Hn.
lhs nrapply H.
nrapply nth'_cons.
Defined.
Definition nth_app@{i|} {A : Type@{i}} (l l' : list A) (n : nat)
(H : (n < length l)%nat)
: nth (l ++ l') n = nth l n.
Proof.
induction l as [|a l IHl] in l', n, H |- × using list_ind@{i i}.
1: destruct (not_lt_zero_r _ H).
destruct n.
1: reflexivity.
by apply IHl, leq_pred'.
Defined.
(H : (n < length l)%nat)
: nth (l ++ l') n = nth l n.
Proof.
induction l as [|a l IHl] in l', n, H |- × using list_ind@{i i}.
1: destruct (not_lt_zero_r _ H).
destruct n.
1: reflexivity.
by apply IHl, leq_pred'.
Defined.
Definition nth_last {A : Type} (l : list A) (i : nat) (p : nat_pred (length l) = i)
: nth l i = last l.
Proof.
destruct p.
induction l as [|a l IHl].
1: reflexivity.
destruct l as [|b l].
1: reflexivity.
cbn; apply IHl.
Defined.
: nth l i = last l.
Proof.
destruct p.
induction l as [|a l IHl].
1: reflexivity.
destruct l as [|b l].
1: reflexivity.
cbn; apply IHl.
Defined.
The last element of a list with an element appended is the appended element.
Definition last_app {A : Type} (l : list A) (x : A)
: last (l ++ [x]) = Some x.
Proof.
induction l as [|a l IHl] in x |- ×.
1: reflexivity.
destruct l.
1: reflexivity.
cbn; apply IHl.
Defined.
: last (l ++ [x]) = Some x.
Proof.
induction l as [|a l IHl] in x |- ×.
1: reflexivity.
destruct l.
1: reflexivity.
cbn; apply IHl.
Defined.
Removing elements
Drop
Fixpoint drop {A : Type} (n : nat) (l : list A) : list A :=
match l, n with
| _ :: l, n.+1%nat ⇒ drop n l
| _, _ ⇒ l
end.
match l, n with
| _ :: l, n.+1%nat ⇒ drop n l
| _, _ ⇒ l
end.
A drop of zero elements is the identity.
A drop of one element is the tail of the list.
Definition drop_1 {A : Type} (l : list A)
: drop 1 l = tail l.
Proof.
induction l.
1: reflexivity.
by destruct l.
Defined.
: drop 1 l = tail l.
Proof.
induction l.
1: reflexivity.
by destruct l.
Defined.
A drop of the empty list is the empty list.
Definition drop_length_leq@{i|} {A : Type@{i}} (n : nat) (l : list A)
(H : (length l ≤ n)%nat)
: drop n l = nil.
Proof.
induction l as [|a l IHl] in H, n |- × using list_ind@{i i}.
1: apply drop_nil.
destruct n.
1: destruct (not_lt_zero_r _ H).
cbn; apply IHl.
apply leq_pred'.
exact H.
Defined.
(H : (length l ≤ n)%nat)
: drop n l = nil.
Proof.
induction l as [|a l IHl] in H, n |- × using list_ind@{i i}.
1: apply drop_nil.
destruct n.
1: destruct (not_lt_zero_r _ H).
cbn; apply IHl.
apply leq_pred'.
exact H.
Defined.
Definition length_drop@{i|} {A : Type@{i}} (n : nat) (l : list A)
: length (drop n l) = (length l - n)%nat.
Proof.
induction l as [|a l IHl] in n |- × using list_ind@{i i}.
1: by rewrite drop_nil.
destruct n.
1: reflexivity.
exact (IHl n).
Defined.
: length (drop n l) = (length l - n)%nat.
Proof.
induction l as [|a l IHl] in n |- × using list_ind@{i i}.
1: by rewrite drop_nil.
destruct n.
1: reflexivity.
exact (IHl n).
Defined.
An element of a drop is an element of the original list.
Definition drop_inlist@{i|} {A : Type@{i}} (n : nat) (l : list A) (x : A)
: InList x (drop n l) → InList x l.
Proof.
intros H.
induction l as [|a l IHl] in n, H, x |- × using list_ind@{i i}.
1: rewrite drop_nil in H; contradiction.
destruct n.
1: rewrite drop_0 in H; assumption.
right; nrapply (IHl _ _ H).
Defined.
: InList x (drop n l) → InList x l.
Proof.
intros H.
induction l as [|a l IHl] in n, H, x |- × using list_ind@{i i}.
1: rewrite drop_nil in H; contradiction.
destruct n.
1: rewrite drop_0 in H; assumption.
right; nrapply (IHl _ _ H).
Defined.
Fixpoint take {A : Type} (n : nat) (l : list A) : list A :=
match l, n with
| x :: l, n.+1%nat ⇒ x :: take n l
| _, _ ⇒ nil
end.
match l, n with
| x :: l, n.+1%nat ⇒ x :: take n l
| _, _ ⇒ nil
end.
A take of zero elements is the empty list.
A take of the empty list is the empty list.
Definition take_length_leq@{i|} {A : Type@{i}} (n : nat) (l : list A)
(H : (length l ≤ n)%nat)
: take n l = l.
Proof.
induction l as [|a l IHl] in H, n |- × using list_ind@{i i}.
1: apply take_nil.
destruct n.
1: destruct (not_lt_zero_r _ H).
cbn; f_ap.
by apply IHl, leq_pred'.
Defined.
(H : (length l ≤ n)%nat)
: take n l = l.
Proof.
induction l as [|a l IHl] in H, n |- × using list_ind@{i i}.
1: apply take_nil.
destruct n.
1: destruct (not_lt_zero_r _ H).
cbn; f_ap.
by apply IHl, leq_pred'.
Defined.
Definition length_take@{i|} {A : Type@{i}} (n : nat) (l : list A)
: length (take n l) = nat_min n (length l).
Proof.
induction l as [|a l IHl] in n |- × using list_ind@{i i}.
{ rewrite take_nil.
rewrite nat_min_r.
1: reflexivity.
cbn; exact _. }
destruct n.
1: reflexivity.
cbn; f_ap.
Defined.
: length (take n l) = nat_min n (length l).
Proof.
induction l as [|a l IHl] in n |- × using list_ind@{i i}.
{ rewrite take_nil.
rewrite nat_min_r.
1: reflexivity.
cbn; exact _. }
destruct n.
1: reflexivity.
cbn; f_ap.
Defined.
An element of a take is an element of the original list.
Definition take_inlist@{i|} {A : Type@{i}} (n : nat) (l : list A) (x : A)
: InList x (take n l) → InList x l.
Proof.
intros H.
induction l as [|a l IHl] in n, H, x |- × using list_ind@{i i}.
1: rewrite take_nil in H; contradiction.
destruct n.
1: rewrite take_0 in H; contradiction.
destruct H as [-> | H].
- left; reflexivity.
- right; exact (IHl _ _ H).
Defined.
: InList x (take n l) → InList x l.
Proof.
intros H.
induction l as [|a l IHl] in n, H, x |- × using list_ind@{i i}.
1: rewrite take_nil in H; contradiction.
destruct n.
1: rewrite take_0 in H; contradiction.
destruct H as [-> | H].
- left; reflexivity.
- right; exact (IHl _ _ H).
Defined.
Removing the first element of a list is the tail of the list.
Definition remove_0 {A : Type} (l : list A) : remove 0 l = tail l.
Proof.
unfold remove.
by rewrite take_0, drop_1.
Defined.
Proof.
unfold remove.
by rewrite take_0, drop_1.
Defined.
Definition remove_length_leq {A : Type} (n : nat) (l : list A)
(H : (length l ≤ n)%nat)
: remove n l = l.
Proof.
unfold remove.
rewrite take_length_leq.
2: exact _.
rewrite drop_length_leq.
2: exact _.
apply app_nil.
Defined.
(H : (length l ≤ n)%nat)
: remove n l = l.
Proof.
unfold remove.
rewrite take_length_leq.
2: exact _.
rewrite drop_length_leq.
2: exact _.
apply app_nil.
Defined.
The length of a remove n is the length of the original list minus one.
Definition length_remove@{i|} {A : Type@{i}} (n : nat) (l : list A)
(H : (n < length l)%nat)
: length (remove n l) = nat_pred (length l)%nat.
Proof.
unfold remove.
rewrite length_app@{i}.
rewrite length_take.
rewrite length_drop.
rewrite nat_min_l.
2: exact (leq_trans _ H).
rewrite <- nat_sub_l_add_r.
2: exact _.
lhs nrapply nat_sub_succ_r.
apply ap.
apply nat_add_sub_cancel_l.
Defined.
(H : (n < length l)%nat)
: length (remove n l) = nat_pred (length l)%nat.
Proof.
unfold remove.
rewrite length_app@{i}.
rewrite length_take.
rewrite length_drop.
rewrite nat_min_l.
2: exact (leq_trans _ H).
rewrite <- nat_sub_l_add_r.
2: exact _.
lhs nrapply nat_sub_succ_r.
apply ap.
apply nat_add_sub_cancel_l.
Defined.
An element of a remove is an element of the original list.
Definition remove_inlist {A : Type} (n : nat) (l : list A) (x : A)
: InList x (remove n l) → InList x l.
Proof.
unfold remove.
intros p.
apply equiv_inlist_app in p.
revert p.
snrapply sum_rec.
- apply take_inlist.
- apply drop_inlist.
Defined.
: InList x (remove n l) → InList x l.
Proof.
unfold remove.
intros p.
apply equiv_inlist_app in p.
revert p.
snrapply sum_rec.
- apply take_inlist.
- apply drop_inlist.
Defined.
Fixpoint list_filter@{u v|} {A : Type@{u}} (l : list A) (P : A → Type@{v})
(dec : ∀ x, Decidable (P x))
: list A
:= match l with
| nil ⇒ nil
| x :: l ⇒
if dec x then x :: list_filter l P dec
else list_filter l P dec
end.
Definition inlist_filter@{u v k | u ≤ k, v ≤ k} {A : Type@{u}} (l : list A)
(P : A → Type@{v}) (dec : ∀ x, Decidable (P x)) (x : A)
: iff@{u k k} (InList x (list_filter l P dec)) (InList x l ∧ P x).
Proof.
simple_list_induction l a l IHl.
- simpl.
apply iff_inverse.
apply iff_equiv.
snrapply prod_empty_l@{v}.
- simpl.
nrapply iff_compose.
2: { apply iff_inverse.
apply iff_equiv.
exact (sum_distrib_r@{k k k _ _ _ k k} _ _ _). }
destruct (dec a) as [p|p].
+ simpl.
snrapply iff_compose.
1: exact (sum (a = x) (prod (InList@{u} x l) (P x))).
1: split; apply functor_sum; only 1,3: exact idmap; apply IHl.
split; apply functor_sum@{k k k k}; only 2,4: apply idmap.
× intros [].
exact (idpath, p).
× exact fst.
+ nrapply iff_compose.
1: apply IHl.
apply iff_inverse.
apply iff_equiv.
nrefine (equiv_compose'@{k k k} (sum_empty_l@{k} _) _).
snrapply equiv_functor_sum'@{k k k k k k}.
2: exact equiv_idmap.
apply equiv_to_empty.
by intros [[] r].
Defined.
Definition list_filter_app {A : Type} (l l' : list A) (P : A → Type)
(dec : ∀ x, Decidable (P x))
: list_filter (l ++ l') P dec = list_filter l P dec ++ list_filter l' P dec.
Proof.
simple_list_induction l a l IHl.
- reflexivity.
- simpl; destruct (dec a); trivial.
simpl; f_ap.
Defined.
(dec : ∀ x, Decidable (P x))
: list A
:= match l with
| nil ⇒ nil
| x :: l ⇒
if dec x then x :: list_filter l P dec
else list_filter l P dec
end.
Definition inlist_filter@{u v k | u ≤ k, v ≤ k} {A : Type@{u}} (l : list A)
(P : A → Type@{v}) (dec : ∀ x, Decidable (P x)) (x : A)
: iff@{u k k} (InList x (list_filter l P dec)) (InList x l ∧ P x).
Proof.
simple_list_induction l a l IHl.
- simpl.
apply iff_inverse.
apply iff_equiv.
snrapply prod_empty_l@{v}.
- simpl.
nrapply iff_compose.
2: { apply iff_inverse.
apply iff_equiv.
exact (sum_distrib_r@{k k k _ _ _ k k} _ _ _). }
destruct (dec a) as [p|p].
+ simpl.
snrapply iff_compose.
1: exact (sum (a = x) (prod (InList@{u} x l) (P x))).
1: split; apply functor_sum; only 1,3: exact idmap; apply IHl.
split; apply functor_sum@{k k k k}; only 2,4: apply idmap.
× intros [].
exact (idpath, p).
× exact fst.
+ nrapply iff_compose.
1: apply IHl.
apply iff_inverse.
apply iff_equiv.
nrefine (equiv_compose'@{k k k} (sum_empty_l@{k} _) _).
snrapply equiv_functor_sum'@{k k k k k k}.
2: exact equiv_idmap.
apply equiv_to_empty.
by intros [[] r].
Defined.
Definition list_filter_app {A : Type} (l l' : list A) (P : A → Type)
(dec : ∀ x, Decidable (P x))
: list_filter (l ++ l') P dec = list_filter l P dec ++ list_filter l' P dec.
Proof.
simple_list_induction l a l IHl.
- reflexivity.
- simpl; destruct (dec a); trivial.
simpl; f_ap.
Defined.
Definition length_seq_rev@{} (n : nat)
: length (seq_rev n) = n.
Proof.
induction n as [|n IHn].
1: reflexivity.
cbn; f_ap.
Defined.
: length (seq_rev n) = n.
Proof.
induction n as [|n IHn].
1: reflexivity.
cbn; f_ap.
Defined.
The length of a sequence of n numbers is n.
Definition length_seq@{} (n : nat)
: length (seq n) = n.
Proof.
lhs nrapply length_reverse.
apply length_seq_rev.
Defined.
: length (seq n) = n.
Proof.
lhs nrapply length_reverse.
apply length_seq_rev.
Defined.
The reversed sequence of n.+1 numbers is the n followed by the rest of the reversed sequence.
Definition seq_rev_cons@{} (n : nat)
: seq_rev n.+1 = n :: seq_rev n.
Proof.
induction n as [|n IHn].
1: reflexivity.
cbn; f_ap.
Defined.
: seq_rev n.+1 = n :: seq_rev n.
Proof.
induction n as [|n IHn].
1: reflexivity.
cbn; f_ap.
Defined.
The sequence of n.+1 numbers is the sequence of n numbers concatenated with [n].
Definition seq_rev'@{} (n : nat) : list {k : nat & (k < n)%nat}.
Proof.
transparent assert (f : (∀ n, {k : nat & (k < n)%nat}
→ {k : nat & (k < n.+1)%nat})).
{ intros m.
snrapply (functor_sigma idmap).
intros k H.
exact (leq_succ_r H). }
induction n as [|n IHn].
1: exact nil.
nrefine ((n; _) :: list_map (f n) IHn).
exact _.
Defined.
Proof.
transparent assert (f : (∀ n, {k : nat & (k < n)%nat}
→ {k : nat & (k < n.+1)%nat})).
{ intros m.
snrapply (functor_sigma idmap).
intros k H.
exact (leq_succ_r H). }
induction n as [|n IHn].
1: exact nil.
nrefine ((n; _) :: list_map (f n) IHn).
exact _.
Defined.
Definition length_seq_rev'@{} (n : nat)
: length (seq_rev' n) = n.
Proof.
induction n as [|n IHn].
1: reflexivity.
cbn; f_ap.
lhs nrapply length_list_map.
exact IHn.
Defined.
: length (seq_rev' n) = n.
Proof.
induction n as [|n IHn].
1: reflexivity.
cbn; f_ap.
lhs nrapply length_list_map.
exact IHn.
Defined.
Definition length_seq'@{} (n : nat)
: length (seq' n) = n.
Proof.
lhs nrapply length_reverse.
apply length_seq_rev'.
Defined.
: length (seq' n) = n.
Proof.
lhs nrapply length_reverse.
apply length_seq_rev'.
Defined.
Definition seq_rev_seq_rev'@{} (n : nat)
: list_map pr1 (seq_rev' n) = seq_rev n.
Proof.
induction n as [|n IHn].
1: reflexivity.
simpl; f_ap.
lhs_V nrapply list_map_compose.
apply IHn.
Defined.
: list_map pr1 (seq_rev' n) = seq_rev n.
Proof.
induction n as [|n IHn].
1: reflexivity.
simpl; f_ap.
lhs_V nrapply list_map_compose.
apply IHn.
Defined.
Definition seq_seq'@{} (n : nat)
: list_map pr1 (seq' n) = seq n.
Proof.
lhs nrapply list_map_reverse_acc.
apply (ap reverse).
apply seq_rev_seq_rev'.
Defined.
: list_map pr1 (seq' n) = seq n.
Proof.
lhs nrapply list_map_reverse_acc.
apply (ap reverse).
apply seq_rev_seq_rev'.
Defined.
Definition nth_seq_rev@{} {n i} (H : (i < n)%nat)
: nth (seq_rev n) i = Some (n - i.+1)%nat.
Proof.
induction i as [|i IHi] in n, H |- ×.
- induction n.
1: destruct (not_lt_zero_r _ H).
cbn; by rewrite nat_sub_zero_r.
- induction n as [|n IHn].
1: destruct (not_lt_zero_r _ H).
by apply IHi, leq_pred'.
Defined.
: nth (seq_rev n) i = Some (n - i.+1)%nat.
Proof.
induction i as [|i IHi] in n, H |- ×.
- induction n.
1: destruct (not_lt_zero_r _ H).
cbn; by rewrite nat_sub_zero_r.
- induction n as [|n IHn].
1: destruct (not_lt_zero_r _ H).
by apply IHi, leq_pred'.
Defined.
Definition nth_seq@{} {n i} (H : (i < n)%nat)
: nth (seq n) i = Some i.
Proof.
induction n.
1: destruct (not_lt_zero_r _ H).
rewrite seq_succ.
destruct (dec (i < n)%nat) as [H'|H'].
- lhs nrapply nth_app.
1: by rewrite length_seq.
by apply IHn.
- apply geq_iff_not_lt in H'.
apply leq_pred' in H.
destruct (leq_antisym H H').
lhs nrapply nth_last.
{ rewrite length_app.
rewrite nat_add_comm.
apply length_seq. }
nrapply last_app.
Defined.
: nth (seq n) i = Some i.
Proof.
induction n.
1: destruct (not_lt_zero_r _ H).
rewrite seq_succ.
destruct (dec (i < n)%nat) as [H'|H'].
- lhs nrapply nth_app.
1: by rewrite length_seq.
by apply IHn.
- apply geq_iff_not_lt in H'.
apply leq_pred' in H.
destruct (leq_antisym H H').
lhs nrapply nth_last.
{ rewrite length_app.
rewrite nat_add_comm.
apply length_seq. }
nrapply last_app.
Defined.
Definition nth'_seq'@{} (n i : nat) (H : (i < length (seq' n))%nat)
: (nth' (seq' n) i H).1 = i.
Proof.
unshelve lhs_V nrapply nth'_list_map.
1: by rewrite length_list_map.
unshelve lhs nrapply (ap011D (fun x y ⇒ nth' x _ y) _ idpath).
2: apply seq_seq'.
apply isinj_some.
lhs_V nrapply nth_nth'.
apply nth_seq.
by rewrite length_seq' in H.
Defined.
Definition inlist_seq@{} (n : nat) x
: InList x (seq n) <~> (x < n)%nat.
Proof.
simple_induction n n IHn.
{ symmetry; apply equiv_to_empty.
apply not_lt_zero_r. }
refine (_ oE equiv_transport _ (seq_succ _)).
nrefine (_ oE (equiv_inlist_app _ _ _)^-1).
nrefine (_ oE equiv_functor_sum' (B':=x = n) IHn _).
2: { simpl.
exact (equiv_path_inverse _ _ oE sum_empty_r@{Set} _). }
nrefine (_ oE equiv_leq_lt_or_eq^-1).
rapply equiv_iff_hprop.
Defined.
: (nth' (seq' n) i H).1 = i.
Proof.
unshelve lhs_V nrapply nth'_list_map.
1: by rewrite length_list_map.
unshelve lhs nrapply (ap011D (fun x y ⇒ nth' x _ y) _ idpath).
2: apply seq_seq'.
apply isinj_some.
lhs_V nrapply nth_nth'.
apply nth_seq.
by rewrite length_seq' in H.
Defined.
Definition inlist_seq@{} (n : nat) x
: InList x (seq n) <~> (x < n)%nat.
Proof.
simple_induction n n IHn.
{ symmetry; apply equiv_to_empty.
apply not_lt_zero_r. }
refine (_ oE equiv_transport _ (seq_succ _)).
nrefine (_ oE (equiv_inlist_app _ _ _)^-1).
nrefine (_ oE equiv_functor_sum' (B':=x = n) IHn _).
2: { simpl.
exact (equiv_path_inverse _ _ oE sum_empty_r@{Set} _). }
nrefine (_ oE equiv_leq_lt_or_eq^-1).
rapply equiv_iff_hprop.
Defined.
Definition length_repeat@{i|} {A : Type@{i}} (n : nat) (x : A)
: length (repeat x n) = n.
Proof.
induction n using nat_ind@{i}.
- reflexivity.
- exact (ap S IHn).
Defined.
: length (repeat x n) = n.
Proof.
induction n using nat_ind@{i}.
- reflexivity.
- exact (ap S IHn).
Defined.
An element of a repeated list is equal to the repeated element.
Definition inlist_repeat@{i|} {A : Type@{i}} (n : nat) (x y : A)
: InList y (repeat x n) → y = x.
Proof.
induction n as [|n IHn].
1:contradiction.
intros [p | i].
- by symmetry.
- by apply IHn.
Defined.
: InList y (repeat x n) → y = x.
Proof.
induction n as [|n IHn].
1:contradiction.
intros [p | i].
- by symmetry.
- by apply IHn.
Defined.
Forall
Definition for_all_inlist {A : Type} (P : A → Type) l
: (∀ x, InList x l → P x) → for_all P l.
Proof.
simple_list_induction l h t IHl; intros H; cbn; trivial; split.
- apply H.
by left.
- apply IHl.
intros y i.
apply H.
by right.
Defined.
: (∀ x, InList x l → P x) → for_all P l.
Proof.
simple_list_induction l h t IHl; intros H; cbn; trivial; split.
- apply H.
by left.
- apply IHl.
intros y i.
apply H.
by right.
Defined.
Definition inlist_for_all {A : Type} {P : A → Type}
(l : list A)
: for_all P l → ∀ x, InList x l → P x.
Proof.
simple_list_induction l x l IHl.
- contradiction.
- intros [Hx Hl] y [-> | i].
+ exact Hx.
+ apply IHl.
1: exact Hl.
exact i.
Defined.
(l : list A)
: for_all P l → ∀ x, InList x l → P x.
Proof.
simple_list_induction l x l IHl.
- contradiction.
- intros [Hx Hl] y [-> | i].
+ exact Hx.
+ apply IHl.
1: exact Hl.
exact i.
Defined.
If a predicate P implies a predicate Q composed with a function f, then for_all P l implies for_all Q (list_map f l).
Definition for_all_list_map {A B : Type} (P : A → Type) (Q : B → Type)
(f : A → B) (Hf : ∀ x, P x → Q (f x))
: ∀ l, for_all P l → for_all Q (list_map f l).
Proof.
simple_list_induction l x l IHl; simpl; trivial.
intros [Hx Hl].
split; auto.
Defined.
(f : A → B) (Hf : ∀ x, P x → Q (f x))
: ∀ l, for_all P l → for_all Q (list_map f l).
Proof.
simple_list_induction l x l IHl; simpl; trivial.
intros [Hx Hl].
split; auto.
Defined.
Definition for_all_list_map' {A B : Type} (P : B → Type) (f : A → B)
: ∀ l, for_all (P o f) l → for_all P (list_map f l).
Proof.
by apply for_all_list_map.
Defined.
: ∀ l, for_all (P o f) l → for_all P (list_map f l).
Proof.
by apply for_all_list_map.
Defined.
If a predicate P and a predicate Q together imply a predicate R, then for_all P l and for_all Q l together imply for_all R l. There are also some side conditions for the default elements.
Lemma for_all_list_map2 {A B C : Type}
(P : A → Type) (Q : B → Type) (R : C → Type)
(f : A → B → C) (Hf : ∀ x y, P x → Q y → R (f x y))
def_l (Hdefl : ∀ l1, for_all P l1 → for_all R (def_l l1))
def_r (Hdefr : ∀ l2, for_all Q l2 → for_all R (def_r l2))
(l1 : list A) (l2 : list B)
: for_all P l1 → for_all Q l2
→ for_all R (list_map2 f def_l def_r l1 l2).
Proof.
revert l2;
simple_list_induction l1 x l1 IHl1;
intro l2.
- destruct l2 as [|y l2]; cbn; auto.
- simpl. destruct l2 as [|y l2]; intros [Hx Hl1];
[intros _ | intros [Hy Hl2] ]; simpl; auto.
apply Hdefl.
simpl; auto.
Defined.
(P : A → Type) (Q : B → Type) (R : C → Type)
(f : A → B → C) (Hf : ∀ x y, P x → Q y → R (f x y))
def_l (Hdefl : ∀ l1, for_all P l1 → for_all R (def_l l1))
def_r (Hdefr : ∀ l2, for_all Q l2 → for_all R (def_r l2))
(l1 : list A) (l2 : list B)
: for_all P l1 → for_all Q l2
→ for_all R (list_map2 f def_l def_r l1 l2).
Proof.
revert l2;
simple_list_induction l1 x l1 IHl1;
intro l2.
- destruct l2 as [|y l2]; cbn; auto.
- simpl. destruct l2 as [|y l2]; intros [Hx Hl1];
[intros _ | intros [Hy Hl2] ]; simpl; auto.
apply Hdefl.
simpl; auto.
Defined.
A simpler variant of for_all_map2 where both lists have the same length and the side conditions on the default elements can be avoided.
Definition for_all_list_map2' {A B C : Type}
(P : A → Type) (Q : B → Type) (R : C → Type)
(f : A → B → C) (Hf : ∀ x y, P x → Q y → R (f x y))
{def_l def_r} {l1 : list A} {l2 : list B}
(p : length l1 = length l2)
: for_all P l1 → for_all Q l2
→ for_all R (list_map2 f def_l def_r l1 l2).
Proof.
revert l2 p;
simple_list_induction l1 x l1 IHl1;
intros l2 p.
- destruct l2.
+ reflexivity.
+ discriminate.
- destruct l2 as [|y l2].
+ discriminate.
+ intros [Hx Hl1] [Hy Hl2].
split.
× by apply Hf.
× apply IHl1; trivial.
apply path_nat_succ.
exact p.
Defined.
(P : A → Type) (Q : B → Type) (R : C → Type)
(f : A → B → C) (Hf : ∀ x y, P x → Q y → R (f x y))
{def_l def_r} {l1 : list A} {l2 : list B}
(p : length l1 = length l2)
: for_all P l1 → for_all Q l2
→ for_all R (list_map2 f def_l def_r l1 l2).
Proof.
revert l2 p;
simple_list_induction l1 x l1 IHl1;
intros l2 p.
- destruct l2.
+ reflexivity.
+ discriminate.
- destruct l2 as [|y l2].
+ discriminate.
+ intros [Hx Hl1] [Hy Hl2].
split.
× by apply Hf.
× apply IHl1; trivial.
apply path_nat_succ.
exact p.
Defined.
The left fold of f on a list l for which for_all Q l satisfies P if P and Q imply P composed with f.
Lemma fold_left_preserves {A B : Type}
(P : A → Type) (Q : B → Type) (f : A → B → A)
(Hf : ∀ x y, P x → Q y → P (f x y))
(acc : A) (Ha : P acc) (l : list B) (Hl : for_all Q l)
: P (fold_left f l acc).
Proof.
revert acc Ha Hl;
simple_list_induction l x l IHl;
intros acc Ha Hl.
- exact Ha.
- simpl.
destruct Hl as [Qx Hl].
apply IHl; auto.
Defined.
(P : A → Type) (Q : B → Type) (f : A → B → A)
(Hf : ∀ x y, P x → Q y → P (f x y))
(acc : A) (Ha : P acc) (l : list B) (Hl : for_all Q l)
: P (fold_left f l acc).
Proof.
revert acc Ha Hl;
simple_list_induction l x l IHl;
intros acc Ha Hl.
- exact Ha.
- simpl.
destruct Hl as [Qx Hl].
apply IHl; auto.
Defined.
for_all preserves the truncation predicate.
Definition istrunc_for_all {A : Type}
{n : trunc_index} (P : A → Type) (l : list A)
: for_all (fun x ⇒ IsTrunc n (P x)) l → IsTrunc n (for_all P l).
Proof.
induction l as [|x l IHl]; simpl.
- destruct n; exact _.
- intros [Hx Hl].
apply IHl in Hl.
exact _.
Defined.
Global Instance istrunc_for_all' {A : Type} {n : trunc_index}
(P : A → Type) (l : list A)
`{∀ x, IsTrunc n (P x)}
: IsTrunc n (for_all P l).
Proof.
by apply istrunc_for_all, for_all_inlist.
Defined.
{n : trunc_index} (P : A → Type) (l : list A)
: for_all (fun x ⇒ IsTrunc n (P x)) l → IsTrunc n (for_all P l).
Proof.
induction l as [|x l IHl]; simpl.
- destruct n; exact _.
- intros [Hx Hl].
apply IHl in Hl.
exact _.
Defined.
Global Instance istrunc_for_all' {A : Type} {n : trunc_index}
(P : A → Type) (l : list A)
`{∀ x, IsTrunc n (P x)}
: IsTrunc n (for_all P l).
Proof.
by apply istrunc_for_all, for_all_inlist.
Defined.
If a predicate holds for an element, then it holds for_all the elements of the repeated list.
Definition for_all_repeat {A : Type} {n : nat}
(P : A → Type) (x : A)
: P x → for_all P (repeat x n).
Proof.
intros H.
induction n as [|n IHn].
1: exact tt.
exact (H, IHn).
Defined.
(P : A → Type) (x : A)
: P x → for_all P (repeat x n).
Proof.
intros H.
induction n as [|n IHn].
1: exact tt.
exact (H, IHn).
Defined.
We can form a list of pairs of a sigma type given a list and a for_all predicate over it.
Definition list_sigma {A : Type} (P : A → Type) (l : list A) (p : for_all P l)
: list {x : A & P x}.
Proof.
induction l as [|x l IHl] in p |- ×.
1: exact nil.
destruct p as [Hx Hl].
exact ((x; Hx) :: IHl Hl).
Defined.
: list {x : A & P x}.
Proof.
induction l as [|x l IHl] in p |- ×.
1: exact nil.
destruct p as [Hx Hl].
exact ((x; Hx) :: IHl Hl).
Defined.
The length of a list of sigma types is the same as the original list.
Definition length_list_sigma {A : Type} {P : A → Type} {l : list A} {p : for_all P l}
: length (list_sigma P l p) = length l.
Proof.
revert p; simple_list_induction l x l IHl; intro p.
1: reflexivity.
destruct p as [Hx Hl].
cbn; f_ap.
apply IHl.
Defined.
: length (list_sigma P l p) = length l.
Proof.
revert p; simple_list_induction l x l IHl; intro p.
1: reflexivity.
destruct p as [Hx Hl].
cbn; f_ap.
apply IHl.
Defined.
Global Instance decidable_for_all {A : Type} (P : A → Type)
`{∀ x, Decidable (P x)} (l : list A)
: Decidable (for_all P l).
Proof.
simple_list_induction l x l IHl; exact _.
Defined.
`{∀ x, Decidable (P x)} (l : list A)
: Decidable (for_all P l).
Proof.
simple_list_induction l x l IHl; exact _.
Defined.
Global Instance decidable_list_exists {A : Type} (P : A → Type)
`{∀ x, Decidable (P x)} (l : list A)
: Decidable (list_exists P l).
Proof.
simple_list_induction l x l IHl; exact _.
Defined.
Definition inlist_list_exists {A : Type} (P : A → Type) (l : list A)
: list_exists P l → ∃ (x : A), InList x l ∧ P x.
Proof.
simple_list_induction l x l IHl.
1: done.
simpl.
intros [Px | ex].
- ∃ x.
by split; [left|].
- destruct (IHl ex) as [x' [H Px']].
∃ x'.
by split; [right|].
Defined.
Definition list_exists_inlist {A : Type} (P : A → Type) (l : list A)
: ∀ (x : A), InList x l → P x → list_exists P l.
Proof.
simple_list_induction l x l IHl.
1: trivial.
simpl; intros y H p; revert H.
apply functor_sum.
- exact (fun r ⇒ r^ # p).
- intros H.
by apply (IHl y).
Defined.
Definition list_exists_seq {n : nat} (P : nat → Type)
(H : ∀ k, P k → (k < n)%nat)
: (∃ k, P k) ↔ list_exists P (seq n).
Proof.
split.
- intros [k p].
snrapply (list_exists_inlist P _ k _ p).
apply inlist_seq, H.
exact p.
- intros H1.
apply inlist_list_exists in H1.
destruct H1 as [k [Hk p]].
∃ k.
exact p.
Defined.
`{∀ x, Decidable (P x)} (l : list A)
: Decidable (list_exists P l).
Proof.
simple_list_induction l x l IHl; exact _.
Defined.
Definition inlist_list_exists {A : Type} (P : A → Type) (l : list A)
: list_exists P l → ∃ (x : A), InList x l ∧ P x.
Proof.
simple_list_induction l x l IHl.
1: done.
simpl.
intros [Px | ex].
- ∃ x.
by split; [left|].
- destruct (IHl ex) as [x' [H Px']].
∃ x'.
by split; [right|].
Defined.
Definition list_exists_inlist {A : Type} (P : A → Type) (l : list A)
: ∀ (x : A), InList x l → P x → list_exists P l.
Proof.
simple_list_induction l x l IHl.
1: trivial.
simpl; intros y H p; revert H.
apply functor_sum.
- exact (fun r ⇒ r^ # p).
- intros H.
by apply (IHl y).
Defined.
Definition list_exists_seq {n : nat} (P : nat → Type)
(H : ∀ k, P k → (k < n)%nat)
: (∃ k, P k) ↔ list_exists P (seq n).
Proof.
split.
- intros [k p].
snrapply (list_exists_inlist P _ k _ p).
apply inlist_seq, H.
exact p.
- intros H1.
apply inlist_list_exists in H1.
destruct H1 as [k [Hk p]].
∃ k.
exact p.
Defined.
An upper bound on witnesses of a decidable predicate makes the sigma type decidable.