Built with Alectryon. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use ⌘ instead of Ctrl.
Require Import Basics.Overture Basics.Tactics Basics.PathGroupoids Basics.TruncRequire 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.(** * Theory of Lists and List Operations *)(** In this file we collect lemmas about lists and their operations. We don't include those in [List.Core] so that file can stay lightweight on dependencies. *)(** We generally try to keep the order the same as the concepts appeared in [List.Core]. *)LocalOpen Scope list_scope.LocalOpen Scope nat_scope.(** ** Length *)(** A list of length zero must be the empty list. *)
A: Type l: list A H: length l = 0
l = nil
A: Type l: list A H: length l = 0
l = nil
A: Type H: length nil = 0
nil = nil
A: Type a: A l: list A H: length (a :: l) = 0
a :: l = nil
A: Type H: length nil = 0
nil = nil
reflexivity.
A: Type a: A l: list A H: length (a :: l) = 0
a :: l = nil
discriminate.Defined.(** ** Concatenation *)(** Concatenating the empty list on the right is the identity. *)
A: Type l: list A
l ++ nil = l
A: Type l: list A
l ++ nil = l
A: Type
nil ++ nil = nil
A: Type a: A l: list A IHl: l ++ nil = l
(a :: l) ++ nil = a :: l
A: Type a: A l: list A IHl: l ++ nil = l
(a :: l) ++ nil = a :: l
simpl; f_ap.Defined.(** Associativity of list concatenation. *)
A: Type x, y, z: list A
x ++ y ++ z = (x ++ y) ++ z
A: Type x, y, z: list A
x ++ y ++ z = (x ++ y) ++ z
A: Type y, z: list A
nil ++ y ++ z = (nil ++ y) ++ z
A: Type a: A x, y, z: list A IHx: x ++ y ++ z = (x ++ y) ++ z
(a :: x) ++ y ++ z = ((a :: x) ++ y) ++ z
A: Type y, z: list A
nil ++ y ++ z = (nil ++ y) ++ z
reflexivity.
A: Type a: A x, y, z: list A IHx: x ++ y ++ z = (x ++ y) ++ z
(a :: x) ++ y ++ z = ((a :: x) ++ y) ++ z
exact (ap (cons a) IHx).Defined.(** The type of lists has a monoidal structure given by concatenation. *)
A: Type w, x, y, z: list A
app_assoc w x (y ++ z) @ app_assoc (w ++ x) y z =
(ap (funl : list A => w ++ l) (app_assoc x y z) @ app_assoc w (x ++ y) z) @
ap (funl : list A => l ++ z) (app_assoc w x y)
A: Type w, x, y, z: list A
app_assoc w x (y ++ z) @ app_assoc (w ++ x) y z =
(ap (funl : list A => w ++ l) (app_assoc x y z) @ app_assoc w (x ++ y) z) @
ap (funl : list A => l ++ z) (app_assoc w x y)
A: Type w, x, y, z: list A
(ap (funl : list A => w ++ l) (app_assoc x y z) @ app_assoc w (x ++ y) z) @
ap (funl : list A => l ++ z) (app_assoc w x y) =
app_assoc w x (y ++ z) @ app_assoc (w ++ x) y z
A: Type x, y, z: list A
(ap (funl : list A => nil ++ l) (app_assoc x y z) @ app_assoc nil (x ++ y) z) @
ap (funl : list A => l ++ z) (app_assoc nil x y) =
app_assoc nil x (y ++ z) @ app_assoc (nil ++ x) y z
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
(ap (funl : list A => (a :: w) ++ l) (app_assoc x y z) @
app_assoc (a :: w) (x ++ y) z) @
ap (funl : list A => l ++ z) (app_assoc (a :: w) x y) =
app_assoc (a :: w) x (y ++ z) @ app_assoc ((a :: w) ++ x) y z
A: Type x, y, z: list A
(ap (funl : list A => nil ++ l) (app_assoc x y z) @ app_assoc nil (x ++ y) z) @
ap (funl : list A => l ++ z) (app_assoc nil x y) =
app_assoc nil x (y ++ z) @ app_assoc (nil ++ x) y z
A: Type x, y, z: list A
(ap idmap (app_assoc x y z) @ 1) @ 1 = 1 @ app_assoc x y z
A: Type x, y, z: list A
ap idmap (app_assoc x y z) @ 1 = app_assoc x y z
A: Type x, y, z: list A
ap idmap (app_assoc x y z) = app_assoc x y z
apply ap_idmap.
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
(ap (funl : list A => (a :: w) ++ l) (app_assoc x y z) @
app_assoc (a :: w) (x ++ y) z) @
ap (funl : list A => l ++ z) (app_assoc (a :: w) x y) =
app_assoc (a :: w) x (y ++ z) @ app_assoc ((a :: w) ++ x) y z
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
(ap (funl : list A => a :: w ++ l) (app_assoc x y z) @
ap (cons a) (app_assoc w (x ++ y) z)) @
ap (funl : list A => l ++ z) (ap (cons a) (app_assoc w x y)) =
ap (cons a) (app_assoc w x (y ++ z)) @ ap (cons a) (app_assoc (w ++ x) y z)
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
(ap (funl : list A => a :: w ++ l) (app_assoc x y z) @
ap (cons a) (app_assoc w (x ++ y) z)) @
ap (funl : list A => l ++ z) (ap (cons a) (app_assoc w x y)) =
ap (cons a) (app_assoc w x (y ++ z) @ app_assoc (w ++ x) y z)
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
(ap (funl : list A => a :: w ++ l) (app_assoc x y z) @
ap (cons a) (app_assoc w (x ++ y) z)) @
ap (funl : list A => l ++ z) (ap (cons a) (app_assoc w x y)) =
ap (cons a)
((ap (funl : list A => w ++ l) (app_assoc x y z) @ app_assoc w (x ++ y) z) @
ap (funl : list A => l ++ z) (app_assoc w x y))
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
(ap (funl : list A => a :: w ++ l) (app_assoc x y z) @
ap (cons a) (app_assoc w (x ++ y) z)) @
ap (funl : list A => l ++ z) (ap (cons a) (app_assoc w x y)) =
ap (cons a)
(ap (funl : list A => w ++ l) (app_assoc x y z) @ app_assoc w (x ++ y) z) @
ap (cons a) (ap (funl : list A => l ++ z) (app_assoc w x y))
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
ap (funl : list A => a :: w ++ l) (app_assoc x y z) @
ap (cons a) (app_assoc w (x ++ y) z) =
ap (cons a)
(ap (funl : list A => w ++ l) (app_assoc x y z) @ app_assoc w (x ++ y) z)
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
ap (funl : list A => l ++ z) (ap (cons a) (app_assoc w x y)) =
ap (cons a) (ap (funl : list A => l ++ z) (app_assoc w x y))
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
ap (funl : list A => a :: w ++ l) (app_assoc x y z) @
ap (cons a) (app_assoc w (x ++ y) z) =
ap (cons a)
(ap (funl : list A => w ++ l) (app_assoc x y z) @ app_assoc w (x ++ y) z)
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
ap (funl : list A => a :: w ++ l) (app_assoc x y z) @
ap (cons a) (app_assoc w (x ++ y) z) =
ap (cons a) (ap (funl : list A => w ++ l) (app_assoc x y z)) @
ap (cons a) (app_assoc w (x ++ y) z)
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
ap (funl : list A => a :: w ++ l) (app_assoc x y z) =
ap (cons a) (ap (funl : list A => w ++ l) (app_assoc x y z))
apply ap_compose.
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
ap (funl : list A => l ++ z) (ap (cons a) (app_assoc w x y)) =
ap (cons a) (ap (funl : list A => l ++ z) (app_assoc w x y))
A: Type a: A w, x, y, z: list A IHw: forallx0y0z0 : list A,
(ap (funl : list A => w ++ l) (app_assoc x0 y0 z0) @
app_assoc w (x0 ++ y0) z0) @
ap (funl : list A => l ++ z0) (app_assoc w x0 y0) =
app_assoc w x0 (y0 ++ z0) @ app_assoc (w ++ x0) y0 z0
ap (funx0 : list A => (a :: x0) ++ z) (app_assoc w x y) =
ap (cons a) (ap (funl : list A => l ++ z) (app_assoc w x y))
napply (ap_compose (funl => l ++ z)).Defined.(** The length of a concatenated list is the sum of the lengths of the two lists. *)
A: Type l, l': list A
length (l ++ l') = length l + length l'
A: Type l, l': list A
length (l ++ l') = length l + length l'
A: Type l': list A
length (nil ++ l') = length nil + length l'
A: Type a: A l, l': list A IHl: length (l ++ l') = length l + length l'
length ((a :: l) ++ l') = length (a :: l) + length l'
A: Type a: A l, l': list A IHl: length (l ++ l') = length l + length l'
length ((a :: l) ++ l') = length (a :: l) + length l'
A: Type a: A l, l': list A IHl: length (l ++ l') = length l + length l'
(length (l ++ l')).+1 = (length l + length l').+1
exact (ap S IHl).Defined.(** An element of a concatenated list is equivalently either in the first list or in the second list. *)
A: Type l, l': list A x: A
InList x l + InList x l' <~> InList x (l ++ l')
A: Type l, l': list A x: A
InList x l + InList x l' <~> InList x (l ++ l')
A: Type l': list A x: A
InList x nil + InList x l' <~> InList x (nil ++ l')
A: Type a: A l, l': list A x: A IHl: InList x l + InList x l' <~> InList x (l ++ l')
InList x (a :: l) + InList x l' <~> InList x ((a :: l) ++ l')
A: Type l': list A x: A
InList x nil + InList x l' <~> InList x (nil ++ l')
apply sum_empty_l.
A: Type a: A l, l': list A x: A IHl: InList x l + InList x l' <~> InList x (l ++ l')
InList x (a :: l) + InList x l' <~> InList x ((a :: l) ++ l')
A: Type a: A l, l': list A x: A IHl: InList x l + InList x l' <~> InList x (l ++ l')
(a = x) + (InList x l + InList x l') <~> (a = x) + InList x (l ++ l')
byapply equiv_functor_sum_l.Defined.(** ** Folding *)(** A left fold over a concatenated list is equivalent to folding over the first followed by folding over the second. *)
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)
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)
A, B: Type f: A -> B -> A l': list B i: A
fold_left f (nil ++ l') i = fold_left f l' (fold_left f nil i)
A, B: Type f: A -> B -> A a: B l, l': list B i: A IHl: foralli0 : A, fold_left f (l ++ l') i0 = fold_left f l' (fold_left f l i0)
fold_left f ((a :: l) ++ l') i = fold_left f l' (fold_left f (a :: l) i)
A, B: Type f: A -> B -> A a: B l, l': list B i: A IHl: foralli0 : A, fold_left f (l ++ l') i0 = fold_left f l' (fold_left f l i0)
fold_left f ((a :: l) ++ l') i = fold_left f l' (fold_left f (a :: l) i)
apply IHl.Defined.(** A right fold over a concatenated list is equivalent to folding over the second followed by folding over the first. *)
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
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
A, B: Type f: B -> A -> A i: A l': list B
fold_right f i (nil ++ l') = fold_right f (fold_right f i l') nil
A, B: Type f: B -> A -> A i: A a: B l, l': list B IHl: foralli0 : A,
fold_right f i0 (l ++ l') = fold_right f (fold_right f i0 l') l
fold_right f i ((a :: l) ++ l') = fold_right f (fold_right f i l') (a :: l)
A, B: Type f: B -> A -> A i: A a: B l, l': list B IHl: foralli0 : A,
fold_right f i0 (l ++ l') = fold_right f (fold_right f i0 l') l
fold_right f i ((a :: l) ++ l') = fold_right f (fold_right f i l') (a :: l)
exact (ap (f a) (IHl _)).Defined.(** ** Maps *)(** The length of a mapped list is the same as the length of the original list. *)
A, B: Type f: A -> B l: list A
length (list_map f l) = length l
A, B: Type f: A -> B l: list A
length (list_map f l) = length l
A, B: Type f: A -> B
length (list_map f nil) = length nil
A, B: Type f: A -> B x: A l: list A IHl: length (list_map f l) = length l
length (list_map f (x :: l)) = length (x :: l)
A, B: Type f: A -> B
length (list_map f nil) = length nil
reflexivity.
A, B: Type f: A -> B x: A l: list A IHl: length (list_map f l) = length l
length (list_map f (x :: l)) = length (x :: l)
A, B: Type f: A -> B x: A l: list A IHl: length (list_map f l) = length l
(length (list_map f l)).+1 = (length l).+1
exact (ap S IHl).Defined.(** A function applied to an element of a list is an element of the mapped list. *)
A, B: Type f: A -> B l: list A x: A
InList x l -> InList (f x) (list_map f l)
A, B: Type f: A -> B l: list A x: A
InList x l -> InList (f x) (list_map f l)
A, B: Type f: A -> B x: A
InList x nil -> InList (f x) (list_map f nil)
A, B: Type f: A -> B x: A l: list A IHl: InList x l -> InList (f x) (list_map f l) y: A
InList x (y :: l) -> InList (f x) (list_map f (y :: l))
A, B: Type f: A -> B x: A l: list A IHl: InList x l -> InList (f x) (list_map f l) y: A
InList x (y :: l) -> InList (f x) (list_map f (y :: l))
A, B: Type f: A -> B x: A l: list A IHl: InList x l -> InList (f x) (list_map f l) y: A p: y = x
InList (f x) (list_map f (y :: l))
A, B: Type f: A -> B x: A l: list A IHl: InList x l -> InList (f x) (list_map f l) y: A i: InList x l
InList (f x) (list_map f (y :: l))
A, B: Type f: A -> B x: A l: list A IHl: InList x l -> InList (f x) (list_map f l) y: A p: y = x
InList (f x) (list_map f (y :: l))
A, B: Type f: A -> B x: A l: list A IHl: InList x l -> InList (f x) (list_map f l) y: A p: y = x
f y = f x
exact (ap f p).
A, B: Type f: A -> B x: A l: list A IHl: InList x l -> InList (f x) (list_map f l) y: A i: InList x l
InList (f x) (list_map f (y :: l))
A, B: Type f: A -> B x: A l: list A IHl: InList x l -> InList (f x) (list_map f l) y: A i: InList x l
InList (f x) (list_map f l)
exact (IHl i).Defined.(** An element of a mapped list is equal to the function applied to some element of the original list. *)
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)%type}
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)%type}
A, B: Type f: A -> B x: B
InList x (list_map f nil) -> {y : A & ((f y = x) * InList y nil)%type}
A, B: Type f: A -> B y: A l: list A x: B IHl: InList x (list_map f l) -> {y0 : A & ((f y0 = x) * InList y0 l)%type}
InList x (list_map f (y :: l)) ->
{y0 : A & ((f y0 = x) * InList y0 (y :: l))%type}
A, B: Type f: A -> B y: A l: list A x: B IHl: InList x (list_map f l) -> {y0 : A & ((f y0 = x) * InList y0 l)%type}
InList x (list_map f (y :: l)) ->
{y0 : A & ((f y0 = x) * InList y0 (y :: l))%type}
A, B: Type f: A -> B y: A l: list A x: B IHl: InList x (list_map f l) -> {y0 : A & ((f y0 = x) * InList y0 l)%type} p: f y = x
{y0 : A & ((f y0 = x) * InList y0 (y :: l))%type}
A, B: Type f: A -> B y: A l: list A x: B IHl: InList x (list_map f l) -> {y0 : A & ((f y0 = x) * InList y0 l)%type} i: InList x (list_map f l)
{y0 : A & ((f y0 = x) * InList y0 (y :: l))%type}
A, B: Type f: A -> B y: A l: list A x: B IHl: InList x (list_map f l) -> {y0 : A & ((f y0 = x) * InList y0 l)%type} p: f y = x
{y0 : A & ((f y0 = x) * InList y0 (y :: l))%type}
exact (y; (p, inl idpath)).
A, B: Type f: A -> B y: A l: list A x: B IHl: InList x (list_map f l) -> {y0 : A & ((f y0 = x) * InList y0 l)%type} i: InList x (list_map f l)
{y0 : A & ((f y0 = x) * InList y0 (y :: l))%type}
A, B: Type f: A -> B y: A l: list A x: B IHl: InList x (list_map f l) -> {y0 : A & ((f y0 = x) * InList y0 l)%type} i: InList x (list_map f l) y': A p: f y' = x i': InList y' l
{y0 : A & ((f y0 = x) * InList y0 (y :: l))%type}
exact (y'; (p, inr i')).Defined.(** Mapping a function over a concatenated list is the concatenation of the mapped lists. *)
A, B: Type f: A -> B l, l': list A
list_map f (l ++ l') = list_map f l ++ list_map f l'
A, B: Type f: A -> B l, l': list A
list_map f (l ++ l') = list_map f l ++ list_map f l'
A, B: Type f: A -> B l': list A
list_map f (nil ++ l') = list_map f nil ++ list_map f l'
A, B: Type f: A -> B a: A l, l': list A IHl: list_map f (l ++ l') = list_map f l ++ list_map f l'
list_map f ((a :: l) ++ l') = list_map f (a :: l) ++ list_map f l'
A, B: Type f: A -> B a: A l, l': list A IHl: list_map f (l ++ l') = list_map f l ++ list_map f l'
list_map f ((a :: l) ++ l') = list_map f (a :: l) ++ list_map f l'
simpl; f_ap.Defined.(** A function that acts as the identity on the elements of a list is the identity on the mapped list. *)
A: Type f: A -> A l: list A Hf: forallx : A, InList x l -> f x = x
list_map f l = l
A: Type f: A -> A l: list A Hf: forallx : A, InList x l -> f x = x
list_map f l = l
A: Type f: A -> A Hf: forallx : A, InList x nil -> f x = x
list_map f nil = nil
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l
list_map f (x :: l) = x :: l
A: Type f: A -> A Hf: forallx : A, InList x nil -> f x = x
list_map f nil = nil
reflexivity.
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l
list_map f (x :: l) = x :: l
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l
f x :: list_map f l = x :: l
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l
f x = x
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l
list_map f l = l
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l
f x = x
exact (Hf _ (inl idpath)).
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l
list_map f l = l
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l
forallx0 : A, InList x0 l -> f x0 = x0
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l y: A Hy: InList y l
f y = y
A: Type f: A -> A x: A l: list A Hf: forallx0 : A, InList x0 (x :: l) -> f x0 = x0 IHl: (forallx0 : A, InList x0 l -> f x0 = x0) -> list_map f l = l y: A Hy: InList y l
InList y (x :: l)
byright.Defined.(** A [list_map] of a composition is the composition of the maps. *)
A, B, C: Type f: A -> B g: B -> C l: list A
list_map (funx : A => g (f x)) l = list_map g (list_map f l)
A, B, C: Type f: A -> B g: B -> C l: list A
list_map (funx : A => g (f x)) l = list_map g (list_map f l)
A, B, C: Type f: A -> B g: B -> C
list_map (funx : A => g (f x)) nil = list_map g (list_map f nil)
A, B, C: Type f: A -> B g: B -> C a: A l: list A IHl: list_map (funx : A => g (f x)) l = list_map g (list_map f l)
list_map (funx : A => g (f x)) (a :: l) = list_map g (list_map f (a :: l))
A, B, C: Type f: A -> B g: B -> C a: A l: list A IHl: list_map (funx : A => g (f x)) l = list_map g (list_map f l)
list_map (funx : A => g (f x)) (a :: l) = list_map g (list_map f (a :: l))
simpl; f_ap.Defined.(** TODO: generalize as max *)(** The length of a [list_map2] is the same as the length of the original lists. *)
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C l1: list A l2: list B
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C l1: list A l2: list B p: length l1 = length l2
length (list_map2 f defl defr l1 l2) = length l1
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C l2: list B p: length nil = length l2
length (list_map2 f defl defr nil l2) = length nil
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C x: A l1: list A l2: list B p: length (x :: l1) = length l2 IHl1: foralll0 : list B,
length l1 = length l0 -> length (list_map2 f defl defr l1 l0) = length l1
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C x: A l1: list A l2: list B p: length (x :: l1) = length l2 IHl1: foralll0 : list B,
length l1 = length l0 -> length (list_map2 f defl defr l1 l0) = length l1
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C x: A l1: list A p: length (x :: l1) = length nil IHl1: foralll2 : list B,
length l1 = length l2 -> length (list_map2 f defl defr l1 l2) = length l1
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C x: A l1: list A b: B l2: list B p: length (x :: l1) = length (b :: l2) IHl1: foralll0 : list B,
length l1 = length l0 -> length (list_map2 f defl defr l1 l0) = length l1
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C x: A l1: list A p: length (x :: l1) = length nil IHl1: foralll2 : list B,
length l1 = length l2 -> length (list_map2 f defl defr l1 l2) = length l1
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C x: A l1: list A b: B l2: list B p: length (x :: l1) = length (b :: l2) IHl1: foralll0 : list B,
length l1 = length l0 -> length (list_map2 f defl defr l1 l0) = length l1
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C x: A l1: list A b: B l2: list B p: length (x :: l1) = length (b :: l2) IHl1: foralll0 : list B,
length l1 = length l0 -> length (list_map2 f defl defr l1 l0) = length l1
length (list_map2 f defl defr l1 l2) = length l1
byapply 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. *)
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C l1: list A l2: list B x: C
InList x (list_map2 f defl defr l1 l2) ->
length l1 = length l2 ->
{y : A & {z : B & ((f y z = x) * (InList y l1 * InList z l2))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C l1: list A l2: list B x: C
InList x (list_map2 f defl defr l1 l2) ->
length l1 = length l2 ->
{y : A & {z : B & ((f y z = x) * (InList y l1 * InList z l2))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C l1: list A l2: list B x: C H: InList x (list_map2 f defl defr l1 l2) p: length l1 = length l2
{y : A & {z : B & ((f y z = x) * (InList y l1 * InList z l2))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C l2: list B x: C H: InList x (list_map2 f defl defr nil l2) p: length nil = length l2
{y : A & {z : B & ((f y z = x) * (InList y nil * InList z l2))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A l2: list B x: C H: InList x (list_map2 f defl defr (y :: l1) l2) p: length (y :: l1) = length l2 IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z : B & ((f y0 z = x0) * (InList y0 l1 * InList z l0))%type}}
{y0 : A &
{z : B & ((f y0 z = x) * (InList y0 (y :: l1) * InList z l2))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C l2: list B x: C H: InList x (list_map2 f defl defr nil l2) p: length nil = length l2
{y : A & {z : B & ((f y z = x) * (InList y nil * InList z l2))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C x: C H: InList x (list_map2 f defl defr nil nil) p: length nil = length nil
{y : A & {z : B & ((f y z = x) * (InList y nil * InList z nil))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C b: B l2: list B x: C H: InList x (list_map2 f defl defr nil (b :: l2)) p: length nil = length (b :: l2)
{y : A & {z : B & ((f y z = x) * (InList y nil * InList z (b :: l2)))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C b: B l2: list B x: C H: InList x (list_map2 f defl defr nil (b :: l2)) p: length nil = length (b :: l2)
{y : A & {z : B & ((f y z = x) * (InList y nil * InList z (b :: l2)))%type}}
inversion p.
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A l2: list B x: C H: InList x (list_map2 f defl defr (y :: l1) l2) p: length (y :: l1) = length l2 IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z : B & ((f y0 z = x0) * (InList y0 l1 * InList z l0))%type}}
{y0 : A &
{z : B & ((f y0 z = x) * (InList y0 (y :: l1) * InList z l2))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A x: C H: InList x (list_map2 f defl defr (y :: l1) nil) p: length (y :: l1) = length nil IHl1: forall (l2 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l2) ->
length l1 = length l2 ->
{y0 : A & {z : B & ((f y0 z = x0) * (InList y0 l1 * InList z l2))%type}}
{y0 : A &
{z : B & ((f y0 z = x) * (InList y0 (y :: l1) * InList z nil))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A z: B l2: list B x: C H: InList x (list_map2 f defl defr (y :: l1) (z :: l2)) p: length (y :: l1) = length (z :: l2) IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z0 : B & ((f y0 z0 = x0) * (InList y0 l1 * InList z0 l0))%type}}
{y0 : A &
{z0 : B & ((f y0 z0 = x) * (InList y0 (y :: l1) * InList z0 (z :: l2)))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A z: B l2: list B x: C H: InList x (list_map2 f defl defr (y :: l1) (z :: l2)) p: length (y :: l1) = length (z :: l2) IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z0 : B & ((f y0 z0 = x0) * (InList y0 l1 * InList z0 l0))%type}}
{y0 : A &
{z0 : B & ((f y0 z0 = x) * (InList y0 (y :: l1) * InList z0 (z :: l2)))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A z: B l2: list B x: C q: f y z = x p: length (y :: l1) = length (z :: l2) IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z0 : B & ((f y0 z0 = x0) * (InList y0 l1 * InList z0 l0))%type}}
{y0 : A &
{z0 : B & ((f y0 z0 = x) * (InList y0 (y :: l1) * InList z0 (z :: l2)))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A z: B l2: list B x: C i: InList x (list_map2 f defl defr l1 l2) p: length (y :: l1) = length (z :: l2) IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z0 : B & ((f y0 z0 = x0) * (InList y0 l1 * InList z0 l0))%type}}
{y0 : A &
{z0 : B & ((f y0 z0 = x) * (InList y0 (y :: l1) * InList z0 (z :: l2)))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A z: B l2: list B x: C i: InList x (list_map2 f defl defr l1 l2) p: length (y :: l1) = length (z :: l2) IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z0 : B & ((f y0 z0 = x0) * (InList y0 l1 * InList z0 l0))%type}}
{y0 : A &
{z0 : B & ((f y0 z0 = x) * (InList y0 (y :: l1) * InList z0 (z :: l2)))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A z: B l2: list B x: C i: InList x (list_map2 f defl defr l1 l2) p: length (y :: l1) = length (z :: l2) IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z0 : B & ((f y0 z0 = x0) * (InList y0 l1 * InList z0 l0))%type}}
length l1 = length l2
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A z: B l2: list B x: C i: InList x (list_map2 f defl defr l1 l2) p: length (y :: l1) = length (z :: l2) IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z0 : B & ((f y0 z0 = x0) * (InList y0 l1 * InList z0 l0))%type}} y': A z': B q: f y' z' = x r: InList y' l1 s: InList z' l2
{y0 : A &
{z0 : B & ((f y0 z0 = x) * (InList y0 (y :: l1) * InList z0 (z :: l2)))%type}}
A, B, C: Type f: A -> B -> C defl: list A -> list C defr: list B -> list C y: A l1: list A z: B l2: list B x: C i: InList x (list_map2 f defl defr l1 l2) p: length (y :: l1) = length (z :: l2) IHl1: forall (l0 : list B) (x0 : C),
InList x0 (list_map2 f defl defr l1 l0) ->
length l1 = length l0 ->
{y0 : A & {z0 : B & ((f y0 z0 = x0) * (InList y0 l1 * InList z0 l0))%type}} y': A z': B q: f y' z' = x r: InList y' l1 s: InList z' l2
{y0 : A &
{z0 : B & ((f y0 z0 = x) * (InList y0 (y :: l1) * InList z0 (z :: l2)))%type}}
exact (y'; z'; (q, (inr r, inr s))).Defined.(** [list_map2] is a [list_map] if the first list is a repeated value. *)
A, B, C: Type f: A -> B -> C x: A l: list B defl: list A -> list C defr: list B -> list C
list_map2 f defl defr (repeat x (length l)) l = list_map (f x) l
A, B, C: Type f: A -> B -> C x: A l: list B defl: list A -> list C defr: list B -> list C
list_map2 f defl defr (repeat x (length l)) l = list_map (f x) l
A, B, C: Type f: A -> B -> C x: A defl: list A -> list C defr: list B -> list C
list_map2 f defl defr (repeat x (length nil)) nil = list_map (f x) nil
A, B, C: Type f: A -> B -> C x: A y: B l: list B defl: list A -> list C defr: list B -> list C IHl: list_map2 f defl defr (repeat x (length l)) l = list_map (f x) l
list_map2 f defl defr (repeat x (length (y :: l))) (y :: l) =
list_map (f x) (y :: l)
A, B, C: Type f: A -> B -> C x: A defl: list A -> list C defr: list B -> list C
list_map2 f defl defr (repeat x (length nil)) nil = list_map (f x) nil
reflexivity.
A, B, C: Type f: A -> B -> C x: A y: B l: list B defl: list A -> list C defr: list B -> list C IHl: list_map2 f defl defr (repeat x (length l)) l = list_map (f x) l
list_map2 f defl defr (repeat x (length (y :: l))) (y :: l) =
list_map (f x) (y :: l)
cbn; f_ap.Defined.(** [list_map2] is a [list_map] if the second list is a repeated value. *)
A, B, C: Type f: A -> B -> C y: B l: list A defl: list A -> list C defr: list B -> list C
list_map2 f defl defr l (repeat y (length l)) =
list_map (funx : A => f x y) l
A, B, C: Type f: A -> B -> C y: B l: list A defl: list A -> list C defr: list B -> list C
list_map2 f defl defr l (repeat y (length l)) =
list_map (funx : A => f x y) l
A, B, C: Type f: A -> B -> C y: B defl: list A -> list C defr: list B -> list C
list_map2 f defl defr nil (repeat y (length nil)) =
list_map (funx : A => f x y) nil
A, B, C: Type f: A -> B -> C y: B x: A l: list A defl: list A -> list C defr: list B -> list C IHl: list_map2 f defl defr l (repeat y (length l)) =
list_map (funx0 : A => f x0 y) l
list_map2 f defl defr (x :: l) (repeat y (length (x :: l))) =
list_map (funx0 : A => f x0 y) (x :: l)
A, B, C: Type f: A -> B -> C y: B defl: list A -> list C defr: list B -> list C
list_map2 f defl defr nil (repeat y (length nil)) =
list_map (funx : A => f x y) nil
reflexivity.
A, B, C: Type f: A -> B -> C y: B x: A l: list A defl: list A -> list C defr: list B -> list C IHl: list_map2 f defl defr l (repeat y (length l)) =
list_map (funx0 : A => f x0 y) l
list_map2 f defl defr (x :: l) (repeat y (length (x :: l))) =
list_map (funx0 : A => f x0 y) (x :: l)
cbn; f_ap.Defined.(** ** Reversal *)(** The length of [reverse_acc] is the sum of the lengths of the two lists. *)
A: Type acc, l: list A
length (reverse_acc acc l) = length acc + length l
A: Type acc, l: list A
length (reverse_acc acc l) = length acc + length l
A: Type acc, l: list A
length acc + length l = length (reverse_acc acc l)
A: Type a: A l, l': list A IHl: foralll'0 : list A, reverse (l ++ l'0) = reverse l'0 ++ reverse l
reverse (l ++ l') = reverse l' ++ reverse l
exact (IHl l').Defined.(** [reverse] is involutive. *)
A: Type l: list A
reverse (reverse l) = l
A: Type l: list A
reverse (reverse l) = l
A: Type
reverse (reverse nil) = nil
A: Type a: A l: list A IHl: reverse (reverse l) = l
reverse (reverse (a :: l)) = a :: l
A: Type a: A l: list A IHl: reverse (reverse l) = l
reverse (reverse (a :: l)) = a :: l
A: Type a: A l: list A IHl: reverse (reverse l) = l
reverse (a :: l) = ?Goal
A: Type a: A l: list A IHl: reverse (reverse l) = l
reverse ?Goal = a :: l
A: Type a: A l: list A IHl: reverse (reverse l) = l
reverse (reverse l ++ [a]) = a :: l
A: Type a: A l: list A IHl: reverse (reverse l) = l
reverse [a] ++ reverse (reverse l) = a :: l
exact (ap _ IHl).Defined.(** ** Getting elements *)(** A variant of [nth] that returns an element of the list and a proof that it is the [n]-th element. *)
A: Type l: list A n: nat H: n < length l
{x : A & nth l n = Some x}
A: Type l: list A n: nat H: n < length l
{x : A & nth l n = Some x}
A: Type n: nat H: n < length nil
{x : A & nth nil n = Some x}
A: Type a: A l: list A n: nat H: n < length (a :: l) IHa: foralln0 : nat, n0 < length l -> {x : A & nth l n0 = Some x}
{x : A & nth (a :: l) n = Some x}
A: Type a: A l: list A n: nat H: n < length (a :: l) IHa: foralln0 : nat, n0 < length l -> {x : A & nth l n0 = Some x}
{x : A & nth (a :: l) n = Some x}
A: Type a: A l: list A H: 0 < length (a :: l) IHa: foralln : nat, n < length l -> {x : A & nth l n = Some x}
{x : A & nth (a :: l) 0 = Some x}
A: Type a: A l: list A n: nat H: n.+1 < length (a :: l) IHa: foralln0 : nat, n0 < length l -> {x : A & nth l n0 = Some x}
{x : A & nth (a :: l) n.+1 = Some x}
A: Type a: A l: list A n: nat H: n.+1 < length (a :: l) IHa: foralln0 : nat, n0 < length l -> {x : A & nth l n0 = Some x}
{x : A & nth (a :: l) n.+1 = Some x}
A: Type a: A l: list A n: nat H: n.+1 < length (a :: l) IHa: foralln0 : nat, n0 < length l -> {x : A & nth l n0 = Some x}
n < length l
A: Type a: A l: list A n: nat H: n.+1 < length (a :: l) IHa: foralln0 : nat, n0 < length l -> {x : A & nth l n0 = Some x}
n.+2 <= (length l).+1
exact H.Defined.(** A variant of [nth] that always returns an element when we know that the index is in the list. *)Definitionnth' {A : Type} (l : list A) (n : nat) (H : n < length l) : A
:= pr1 (nth_lt l n H).(** The [nth'] element doesn't depend on the proof that [n < length l]. *)
A: Type l: list A n: nat H, H': n < length l
nth' l n H = nth' l n H'
A: Type l: list A n: nat H, H': n < length l
nth' l n H = nth' l n H'
apply ap, path_ishprop.Defined.(** Two equal lists have the same elements in the same positions. *)
A: Type l1, l2: list A p: l1 = l2 n: nat Hn1: n < length l1 Hn2: n < length l2
nth' l1 n Hn1 = nth' l2 n Hn2
A: Type l1, l2: list A p: l1 = l2 n: nat Hn1: n < length l1 Hn2: n < length l2
nth' l1 n Hn1 = nth' l2 n Hn2
A: Type l1: list A n: nat Hn1, Hn2: n < length l1
nth' l1 n Hn1 = nth' l1 n Hn2
byapply nth'_nth'.Defined.(** The [nth'] element of a list is in the list. *)
A: Type l: list A n: nat H: n < length l
InList (nth' l n H) l
A: Type l: list A n: nat H: n < length l
InList (nth' l n H) l
A: Type n: nat H: n < length nil
InList (nth' nil n H) nil
A: Type a: A l: list A n: nat H: n < length (a :: l) IHa: forall (n0 : nat) (H0 : n0 < length l), InList (nth' l n0 H0) l
InList (nth' (a :: l) n H) (a :: l)
A: Type a: A l: list A n: nat H: n < length (a :: l) IHa: forall (n0 : nat) (H0 : n0 < length l), InList (nth' l n0 H0) l
InList (nth' (a :: l) n H) (a :: l)
A: Type a: A l: list A H: 0 < length (a :: l) IHa: forall (n : nat) (H0 : n < length l), InList (nth' l n H0) l
InList (nth' (a :: l) 0 H) (a :: l)
A: Type a: A l: list A n: nat H: n.+1 < length (a :: l) IHa: forall (n0 : nat) (H0 : n0 < length l), InList (nth' l n0 H0) l
InList (nth' (a :: l) n.+1 H) (a :: l)
A: Type a: A l: list A n: nat H: n.+1 < length (a :: l) IHa: forall (n0 : nat) (H0 : n0 < length l), InList (nth' l n0 H0) l
InList (nth' (a :: l) n.+1 H) (a :: l)
A: Type a: A l: list A n: nat H: n.+1 < length (a :: l) IHa: forall (n0 : nat) (H0 : n0 < length l), InList (nth' l n0 H0) l
InList (nth' (a :: l) n.+1 H) l
apply IHa.Defined.(** The [nth'] element of a list is the same as the one given by [nth]. *)
A: Type l: list A n: nat H: n < length l
nth l n = Some (nth' l n H)
A: Type l: list A n: nat H: n < length l
nth l n = Some (nth' l n H)
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]. *)
A: Type l: list A n: nat x: A H: n < length l H': n.+1 < length (x :: l)
nth' (x :: l) n.+1 H' = nth' l n H
A: Type l: list A n: nat x: A H: n < length l H': n.+1 < length (x :: l)
nth' (x :: l) n.+1 H' = nth' l n H
A: Type l: list A n: nat x: A H: n < length l H': n.+1 < length (x :: l)
Some (nth' (x :: l) n.+1 H') = Some (nth' l n H)
A: Type l: list A n: nat x: A H: n < length l H': n.+1 < length (x :: l)
?Goal0 = Some (nth' (x :: l) n.+1 H')
A: Type l: list A n: nat x: A H: n < length l H': n.+1 < length (x :: l)
?Goal0 = ?Goal
A: Type l: list A n: nat x: A H: n < length l H': n.+1 < length (x :: l)
?Goal = Some (nth' l n H)
A: Type l: list A n: nat x: A H: n < length l H': n.+1 < length (x :: l)
nth (x :: l) n.+1 = nth l n
reflexivity.Defined.(** The [nth' n] element of a concatenated list [l ++ l'] where [n < length l] is the [nth'] element of [l]. *)
A: Type l, l': list A n: nat H: n < length l H': n < length (l ++ l')
nth' (l ++ l') n H' = nth' l n H
A: Type l, l': list A n: nat H: n < length l H': n < length (l ++ l')
nth' (l ++ l') n H' = nth' l n H
A: Type l': list A n: nat H: n < length nil H': n < length (nil ++ l')
nth' (nil ++ l') n H' = nth' nil n H
A: Type a: A l, l': list A n: nat H: n < length (a :: l) H': n < length ((a :: l) ++ l') IHl: forall (l'0 : list A) (n0 : nat) (H0 : n0 < length l)
(H'0 : n0 < length (l ++ l'0)), nth' (l ++ l'0) n0 H'0 = nth' l n0 H0
nth' ((a :: l) ++ l') n H' = nth' (a :: l) n H
A: Type a: A l, l': list A n: nat H: n < length (a :: l) H': n < length ((a :: l) ++ l') IHl: forall (l'0 : list A) (n0 : nat) (H0 : n0 < length l)
(H'0 : n0 < length (l ++ l'0)), nth' (l ++ l'0) n0 H'0 = nth' l n0 H0
nth' ((a :: l) ++ l') n H' = nth' (a :: l) n H
A: Type a: A l, l': list A H: 0 < length (a :: l) H': 0 < length ((a :: l) ++ l') IHl: forall (l'0 : list A) (n : nat) (H0 : n < length l)
(H'0 : n < length (l ++ l'0)), nth' (l ++ l'0) n H'0 = nth' l n H0
nth' ((a :: l) ++ l') 0 H' = nth' (a :: l) 0 H
A: Type a: A l, l': list A n: nat H: n.+1 < length (a :: l) H': n.+1 < length ((a :: l) ++ l') IHl: forall (l'0 : list A) (n0 : nat) (H0 : n0 < length l)
(H'0 : n0 < length (l ++ l'0)), nth' (l ++ l'0) n0 H'0 = nth' l n0 H0
nth' ((a :: l) ++ l') n.+1 H' = nth' (a :: l) n.+1 H
A: Type a: A l, l': list A n: nat H: n.+1 < length (a :: l) H': n.+1 < length ((a :: l) ++ l') IHl: forall (l'0 : list A) (n0 : nat) (H0 : n0 < length l)
(H'0 : n0 < length (l ++ l'0)), nth' (l ++ l'0) n0 H'0 = nth' l n0 H0
nth' ((a :: l) ++ l') n.+1 H' = nth' (a :: l) n.+1 H
byapply IHl.Defined.(** The index of an element in a list is the [n] such that the [nth'] element is the element. *)
A: Type l: list A x: A
InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
A: Type l: list A x: A
InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
A: Type x: A
InList x nil -> {n : nat & {H : n < length nil & nth' nil n H = x}}
A: Type a: A l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
InList x (a :: l) ->
{n : nat & {H : n < length (a :: l) & nth' (a :: l) n H = x}}
A: Type a: A l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
InList x (a :: l) ->
{n : nat & {H : n < length (a :: l) & nth' (a :: l) n H = x}}
A: Type a: A l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}} p: a = x
{n : nat & {H : n < length (a :: l) & nth' (a :: l) n H = x}}
A: Type a: A l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}} i: InList x l
{n : nat & {H : n < length (a :: l) & nth' (a :: l) n H = x}}
A: Type a: A l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}} p: a = x
{n : nat & {H : n < length (a :: l) & nth' (a :: l) n H = x}}
A: Type l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
foralla : A,
a = x -> {n : nat & {H : n < length (a :: l) & nth' (a :: l) n H = x}}
A: Type l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
(fun (y : A) (_ : y = x) =>
{n : nat & {H : n < length (y :: l) & nth' (y :: l) n H = x}}) x 1
A: Type l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
(funn : nat => {H : n < length (x :: l) & nth' (x :: l) n H = x}) 0
A: Type l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
0 < length (x :: l)
A: Type l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}}
0 <=
(fix length (A0 : Type) (l0 : list A0) {struct l0} : nat :=
match l0 with
| nil => 0
| _ :: l1 => (length A0 l1).+1end)
A l
exact _.
A: Type a: A l: list A x: A IHl: InList x l -> {n : nat & {H : n < length l & nth' l n H = x}} i: InList x l
{n : nat & {H : n < length (a :: l) & nth' (a :: l) n H = x}}
A: Type a: A l: list A x: A IHl: InList x l -> {n0 : nat & {H0 : n0 < length l & nth' l n0 H0 = x}} i: InList x l n: nat H: n < length l H': nth' l n H = x
A: Type a: A l: list A x: A IHl: InList x l -> {n0 : nat & {H0 : n0 < length l & nth' l n0 H0 = x}} i: InList x l n: nat H: n < length l H': nth' l n H = x
A: Type a: A l: list A x: A IHl: InList x l -> {n0 : nat & {H0 : n0 < length l & nth' l n0 H0 = x}} i: InList x l n: nat H: n < length l H': nth' l n H = x
n.+1 < (length l).+1
A: Type a: A l: list A x: A IHl: InList x l -> {n0 : nat & {H0 : n0 < length l & nth' l n0 H0 = x}} i: InList x l n: nat H: n < length l H': nth' l n H = x
nth' (a :: l) n.+1?Goal = x
A: Type a: A l: list A x: A IHl: InList x l -> {n0 : nat & {H0 : n0 < length l & nth' l n0 H0 = x}} i: InList x l n: nat H: n < length l H': nth' l n H = x
nth' (a :: l) n.+1 (leq_succ H) = x
A: Type a: A l: list A x: A IHl: InList x l -> {n0 : nat & {H0 : n0 < length l & nth' l n0 H0 = x}} i: InList x l n: nat H: n < length l H': nth' l n H = x
nth' (a :: l) n.+1 (leq_succ H) = nth' l n H
apply nth'_cons.Defined.(** The [nth] element of a map is the function applied optionally to the [nth] element of the original list. *)
A, B: Type f: A -> B l: list A n: nat
nth (list_map f l) n = functor_option f (nth l n)
A, B: Type f: A -> B l: list A n: nat
nth (list_map f l) n = functor_option f (nth l n)
A, B: Type f: A -> B n: nat
nth (list_map f nil) n = functor_option f (nth nil n)
A, B: Type f: A -> B a: A l: list A n: nat IHl: foralln0 : nat, nth (list_map f l) n0 = functor_option f (nth l n0)
nth (list_map f (a :: l)) n = functor_option f (nth (a :: l) n)
A, B: Type f: A -> B a: A l: list A n: nat IHl: foralln0 : nat, nth (list_map f l) n0 = functor_option f (nth l n0)
nth (list_map f (a :: l)) n = functor_option f (nth (a :: l) n)
A, B: Type f: A -> B a: A l: list A IHl: foralln : nat, nth (list_map f l) n = functor_option f (nth l n)
nth (list_map f (a :: l)) 0 = functor_option f (nth (a :: l) 0)
A, B: Type f: A -> B a: A l: list A n: nat IHl: foralln0 : nat, nth (list_map f l) n0 = functor_option f (nth l n0)
nth (list_map f (a :: l)) n.+1 = functor_option f (nth (a :: l) n.+1)
A, B: Type f: A -> B a: A l: list A n: nat IHl: foralln0 : nat, nth (list_map f l) n0 = functor_option f (nth l n0)
nth (list_map f (a :: l)) n.+1 = functor_option f (nth (a :: l) n.+1)
apply IHl.Defined.(** The [nth'] element of a [list_map] is the function applied to the [nth'] element of the original list. *)
A, B: Type f: A -> B l: list A n: nat H: n < length l H': n < length (list_map f l)
nth' (list_map f l) n H' = f (nth' l n H)
A, B: Type f: A -> B l: list A n: nat H: n < length l H': n < length (list_map f l)
nth' (list_map f l) n H' = f (nth' l n H)
A, B: Type f: A -> B n: nat H: n < length nil H': n < length (list_map f nil)
nth' (list_map f nil) n H' = f (nth' nil n H)
A, B: Type f: A -> B a: A l: list A n: nat H: n < length (a :: l) H': n < length (list_map f (a :: l)) IHl: forall (n0 : nat) (H0 : n0 < length l) (H'0 : n0 < length (list_map f l)),
nth' (list_map f l) n0 H'0 = f (nth' l n0 H0)
nth' (list_map f (a :: l)) n H' = f (nth' (a :: l) n H)
A, B: Type f: A -> B a: A l: list A n: nat H: n < length (a :: l) H': n < length (list_map f (a :: l)) IHl: forall (n0 : nat) (H0 : n0 < length l) (H'0 : n0 < length (list_map f l)),
nth' (list_map f l) n0 H'0 = f (nth' l n0 H0)
nth' (list_map f (a :: l)) n H' = f (nth' (a :: l) n H)
A, B: Type f: A -> B a: A l: list A H: 0 < length (a :: l) H': 0 < length (list_map f (a :: l)) IHl: forall (n : nat) (H0 : n < length l) (H'0 : n < length (list_map f l)),
nth' (list_map f l) n H'0 = f (nth' l n H0)
nth' (list_map f (a :: l)) 0 H' = f (nth' (a :: l) 0 H)
A, B: Type f: A -> B a: A l: list A n: nat H: n.+1 < length (a :: l) H': n.+1 < length (list_map f (a :: l)) IHl: forall (n0 : nat) (H0 : n0 < length l) (H'0 : n0 < length (list_map f l)),
nth' (list_map f l) n0 H'0 = f (nth' l n0 H0)
nth' (list_map f (a :: l)) n.+1 H' = f (nth' (a :: l) n.+1 H)
A, B: Type f: A -> B a: A l: list A n: nat H: n.+1 < length (a :: l) H': n.+1 < length (list_map f (a :: l)) IHl: forall (n0 : nat) (H0 : n0 < length l) (H'0 : n0 < length (list_map f l)),
nth' (list_map f l) n0 H'0 = f (nth' l n0 H0)
nth' (list_map f (a :: l)) n.+1 H' = f (nth' (a :: l) n.+1 H)
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. *)
A, B, C: Type f: A -> B -> C l1: list A l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length l1 H': n < length l2 H'': n < length (list_map2 f defl defr l1 l2) p: length l1 = length l2
f (nth' l1 n H) (nth' l2 n H') = nth' (list_map2 f defl defr l1 l2) n H''
A, B, C: Type f: A -> B -> C l1: list A l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length l1 H': n < length l2 H'': n < length (list_map2 f defl defr l1 l2) p: length l1 = length l2
f (nth' l1 n H) (nth' l2 n H') = nth' (list_map2 f defl defr l1 l2) n H''
A, B, C: Type f: A -> B -> C l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length nil H': n < length l2 H'': n < length (list_map2 f defl defr nil l2) p: length nil = length l2
f (nth' nil n H) (nth' l2 n H') = nth' (list_map2 f defl defr nil l2) n H''
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l0)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n0 H0) (nth' l0 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n0 H''0 a: A l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length (a :: l1) H': n < length l2 H'': n < length (list_map2 f defl defr (a :: l1) l2) p: length (a :: l1) = length l2
f (nth' (a :: l1) n H) (nth' l2 n H') =
nth' (list_map2 f defl defr (a :: l1) l2) n H''
A, B, C: Type f: A -> B -> C l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length nil H': n < length l2 H'': n < length (list_map2 f defl defr nil l2) p: length nil = length l2
f (nth' nil n H) (nth' l2 n H') = nth' (list_map2 f defl defr nil l2) n H''
A, B, C: Type f: A -> B -> C n: nat defl: list A -> list C defr: list B -> list C H, H': n < length nil H'': n < length (list_map2 f defl defr nil nil) p: length nil = length nil
f (nth' nil n H) (nth' nil n H') = nth' (list_map2 f defl defr nil nil) n H''
A, B, C: Type f: A -> B -> C b: B l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length nil H': n < length (b :: l2) H'': n < length (list_map2 f defl defr nil (b :: l2)) p: length nil = length (b :: l2)
f (nth' nil n H) (nth' (b :: l2) n H') =
nth' (list_map2 f defl defr nil (b :: l2)) n H''
A, B, C: Type f: A -> B -> C n: nat defl: list A -> list C defr: list B -> list C H, H': n < length nil H'': n < length (list_map2 f defl defr nil nil) p: length nil = length nil
f (nth' nil n H) (nth' nil n H') = nth' (list_map2 f defl defr nil nil) n H''
destruct (not_lt_zero_r _ H).
A, B, C: Type f: A -> B -> C b: B l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length nil H': n < length (b :: l2) H'': n < length (list_map2 f defl defr nil (b :: l2)) p: length nil = length (b :: l2)
f (nth' nil n H) (nth' (b :: l2) n H') =
nth' (list_map2 f defl defr nil (b :: l2)) n H''
inversion p.
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l0)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n0 H0) (nth' l0 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n0 H''0 a: A l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length (a :: l1) H': n < length l2 H'': n < length (list_map2 f defl defr (a :: l1) l2) p: length (a :: l1) = length l2
f (nth' (a :: l1) n H) (nth' l2 n H') =
nth' (list_map2 f defl defr (a :: l1) l2) n H''
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l2 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l2)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l2)),
length l1 = length l2 ->
f (nth' l1 n0 H0) (nth' l2 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l2) n0 H''0 a: A n: nat defl: list A -> list C defr: list B -> list C H: n < length (a :: l1) H': n < length nil H'': n < length (list_map2 f defl defr (a :: l1) nil) p: length (a :: l1) = length nil
f (nth' (a :: l1) n H) (nth' nil n H') =
nth' (list_map2 f defl defr (a :: l1) nil) n H''
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l0)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n0 H0) (nth' l0 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n0 H''0 a: A b: B l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length (a :: l1) H': n < length (b :: l2) H'': n < length (list_map2 f defl defr (a :: l1) (b :: l2)) p: length (a :: l1) = length (b :: l2)
f (nth' (a :: l1) n H) (nth' (b :: l2) n H') =
nth' (list_map2 f defl defr (a :: l1) (b :: l2)) n H''
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l2 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l2)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l2)),
length l1 = length l2 ->
f (nth' l1 n0 H0) (nth' l2 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l2) n0 H''0 a: A n: nat defl: list A -> list C defr: list B -> list C H: n < length (a :: l1) H': n < length nil H'': n < length (list_map2 f defl defr (a :: l1) nil) p: length (a :: l1) = length nil
f (nth' (a :: l1) n H) (nth' nil n H') =
nth' (list_map2 f defl defr (a :: l1) nil) n H''
inversion p.
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l0)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n0 H0) (nth' l0 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n0 H''0 a: A b: B l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n < length (a :: l1) H': n < length (b :: l2) H'': n < length (list_map2 f defl defr (a :: l1) (b :: l2)) p: length (a :: l1) = length (b :: l2)
f (nth' (a :: l1) n H) (nth' (b :: l2) n H') =
nth' (list_map2 f defl defr (a :: l1) (b :: l2)) n H''
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n < length l1) (H'0 : n < length l0)
(H''0 : n < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n H0) (nth' l0 n H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n H''0 a: A b: B l2: list B defl: list A -> list C defr: list B -> list C H: 0 < length (a :: l1) H': 0 < length (b :: l2) H'': 0 < length (list_map2 f defl defr (a :: l1) (b :: l2)) p: length (a :: l1) = length (b :: l2)
f (nth' (a :: l1) 0 H) (nth' (b :: l2) 0 H') =
nth' (list_map2 f defl defr (a :: l1) (b :: l2)) 0 H''
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l0)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n0 H0) (nth' l0 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n0 H''0 a: A b: B l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n.+1 < length (a :: l1) H': n.+1 < length (b :: l2) H'': n.+1 < length (list_map2 f defl defr (a :: l1) (b :: l2)) p: length (a :: l1) = length (b :: l2)
f (nth' (a :: l1) n.+1 H) (nth' (b :: l2) n.+1 H') =
nth' (list_map2 f defl defr (a :: l1) (b :: l2)) n.+1 H''
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n < length l1) (H'0 : n < length l0)
(H''0 : n < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n H0) (nth' l0 n H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n H''0 a: A b: B l2: list B defl: list A -> list C defr: list B -> list C H: 0 < length (a :: l1) H': 0 < length (b :: l2) H'': 0 < length (list_map2 f defl defr (a :: l1) (b :: l2)) p: length (a :: l1) = length (b :: l2)
f (nth' (a :: l1) 0 H) (nth' (b :: l2) 0 H') =
nth' (list_map2 f defl defr (a :: l1) (b :: l2)) 0 H''
reflexivity.
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l0)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n0 H0) (nth' l0 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n0 H''0 a: A b: B l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n.+1 < length (a :: l1) H': n.+1 < length (b :: l2) H'': n.+1 < length (list_map2 f defl defr (a :: l1) (b :: l2)) p: length (a :: l1) = length (b :: l2)
f (nth' (a :: l1) n.+1 H) (nth' (b :: l2) n.+1 H') =
nth' (list_map2 f defl defr (a :: l1) (b :: l2)) n.+1 H''
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l0)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n0 H0) (nth' l0 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n0 H''0 a: A b: B l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n.+1 < length (a :: l1) H': n.+1 < length (b :: l2) H'': n.+1 < length (list_map2 f defl defr (a :: l1) (b :: l2)) p: length (a :: l1) = length (b :: l2)
f (nth' l1 n (leq_pred' H)) (nth' l2 n (leq_pred' H')) =
nth'
((fix list_map2
(A0 B0 C0 : Type) (f0 : A0 -> B0 -> C0) (def_l : list A0 -> list C0)
(def_r : list B0 -> list C0) (l0 : list A0)
(l3 : list B0) {struct l0} : list C0 :=
match l0 with
| nil => match l3 with
| nil => nil
| _ :: _ => def_r l3
end
| x :: l4 =>
match l3 with
| nil => def_l l0
| y :: l5 => f0 x y :: list_map2 A0 B0 C0 f0 def_l def_r l4 l5
endend)
A B C f defl defr l1 l2)
n (leq_pred' H'')
A, B, C: Type f: A -> B -> C l1: list A IHl1: forall (l0 : list B) (n0 : nat) (defl0 : list A -> list C)
(defr0 : list B -> list C) (H0 : n0 < length l1) (H'0 : n0 < length l0)
(H''0 : n0 < length (list_map2 f defl0 defr0 l1 l0)),
length l1 = length l0 ->
f (nth' l1 n0 H0) (nth' l0 n0 H'0) =
nth' (list_map2 f defl0 defr0 l1 l0) n0 H''0 a: A b: B l2: list B n: nat defl: list A -> list C defr: list B -> list C H: n.+1 < length (a :: l1) H': n.+1 < length (b :: l2) H'': n.+1 < length (list_map2 f defl defr (a :: l1) (b :: l2)) p: length (a :: l1) = length (b :: l2)
length l1 = length l2
byapply path_nat_succ.Defined.(** The [nth'] element of a [repeat] is the repeated value. *)
A: Type x: A i, n: nat H: i < length (repeat x n)
nth' (repeat x n) i H = x
A: Type x: A i, n: nat H: i < length (repeat x n)
nth' (repeat x n) i H = x
A: Type x: A i: nat H: i < length (repeat x 0)
nth' (repeat x 0) i H = x
A: Type x: A i, n: nat H: i < length (repeat x n.+1) IHn: forall (i0 : nat) (H0 : i0 < length (repeat x n)),
nth' (repeat x n) i0 H0 = x
nth' (repeat x n.+1) i H = x
A: Type x: A i, n: nat H: i < length (repeat x n.+1) IHn: forall (i0 : nat) (H0 : i0 < length (repeat x n)),
nth' (repeat x n) i0 H0 = x
nth' (repeat x n.+1) i H = x
A: Type x: A n: nat H: 0 < length (repeat x n.+1) IHn: forall (i : nat) (H0 : i < length (repeat x n)), nth' (repeat x n) i H0 = x
nth' (repeat x n.+1) 0 H = x
A: Type x: A i, n: nat H: i.+1 < length (repeat x n.+1) IHn: forall (i0 : nat) (H0 : i0 < length (repeat x n)),
nth' (repeat x n) i0 H0 = x
nth' (repeat x n.+1) i.+1 H = x
A: Type x: A i, n: nat H: i.+1 < length (repeat x n.+1) IHn: forall (i0 : nat) (H0 : i0 < length (repeat x n)),
nth' (repeat x n) i0 H0 = x
nth' (repeat x n.+1) i.+1 H = x
apply IHn.Defined.(** Two lists are equal if their [nth'] elements are equal. *)
A: Type l, l': list A p: length l = length l'
(forall (n : nat) (H : n < length l),
nth' l n H = nth' l' n (transport (lt n) p H)) ->
l = l'
A: Type l, l': list A p: length l = length l'
(forall (n : nat) (H : n < length l),
nth' l n H = nth' l' n (transport (lt n) p H)) ->
l = l'
A: Type l, l': list A p: length l = length l' H: forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l' n (transport (lt n) p H0)
l = l'
A: Type l': list A p: length nil = length l' H: forall (n : nat) (H0 : n < length nil),
nth' nil n H0 = nth' l' n (transport (lt n) p H0)
nil = l'
A: Type a: A l, l': list A p: length (a :: l) = length l' H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' l' n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
a :: l = l'
A: Type l': list A p: length nil = length l' H: forall (n : nat) (H0 : n < length nil),
nth' nil n H0 = nth' l' n (transport (lt n) p H0)
nil = l'
A: Type p: length nil = length nil H: forall (n : nat) (H0 : n < length nil),
nth' nil n H0 = nth' nil n (transport (lt n) p H0)
nil = nil
A: Type a: A l': list A p: length nil = length (a :: l') H: forall (n : nat) (H0 : n < length nil),
nth' nil n H0 = nth' (a :: l') n (transport (lt n) p H0)
nil = a :: l'
A: Type p: length nil = length nil H: forall (n : nat) (H0 : n < length nil),
nth' nil n H0 = nth' nil n (transport (lt n) p H0)
nil = nil
reflexivity.
A: Type a: A l': list A p: length nil = length (a :: l') H: forall (n : nat) (H0 : n < length nil),
nth' nil n H0 = nth' (a :: l') n (transport (lt n) p H0)
nil = a :: l'
discriminate.
A: Type a: A l, l': list A p: length (a :: l) = length l' H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' l' n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
a :: l = l'
A: Type a: A l: list A p: length (a :: l) = length nil H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' nil n (transport (lt n) p H0) IHl: forall (l' : list A) (p0 : length l = length l'),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l' n (transport (lt n) p0 H0)) ->
l = l'
a :: l = nil
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
a :: l = a' :: l'
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
a :: l = a' :: l'
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
a = a'
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
l = l'
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
a = a'
exact (H 0 _).
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
l = l'
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
length l = length l'
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l' n (transport (lt n) ?p H0)
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H0 : n < length (a :: l)),
nth' (a :: l) n H0 = nth' (a' :: l') n (transport (lt n) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n : nat) (H0 : n < length l),
nth' l n H0 = nth' l'0 n (transport (lt n) p0 H0)) ->
l = l'0
forall (n : nat) (H0 : n < length l),
nth' l n H0 =
nth' l' n (transport (lt n) (path_nat_succ (length l) (length l') p) H0)
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n0 : nat) (H0 : n0 < length (a :: l)),
nth' (a :: l) n0 H0 = nth' (a' :: l') n0 (transport (lt n0) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n0 : nat) (H0 : n0 < length l),
nth' l n0 H0 = nth' l'0 n0 (transport (lt n0) p0 H0)) ->
l = l'0 n: nat Hn: n < length l
nth' l n Hn =
nth' l' n (transport (lt n) (path_nat_succ (length l) (length l') p) Hn)
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n0 : nat) (H0 : n0 < length (a :: l)),
nth' (a :: l) n0 H0 = nth' (a' :: l') n0 (transport (lt n0) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n0 : nat) (H0 : n0 < length l),
nth' l n0 H0 = nth' l'0 n0 (transport (lt n0) p0 H0)) ->
l = l'0 n: nat Hn: n < length l
n.+1 < length (a :: l)
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n0 : nat) (H0 : n0 < length (a :: l)),
nth' (a :: l) n0 H0 = nth' (a' :: l') n0 (transport (lt n0) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n0 : nat) (H0 : n0 < length l),
nth' l n0 H0 = nth' l'0 n0 (transport (lt n0) p0 H0)) ->
l = l'0 n: nat Hn: n < length l
nth' (a :: l) n.+1?H' =
nth' l' n (transport (lt n) (path_nat_succ (length l) (length l') p) Hn)
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n0 : nat) (H0 : n0 < length (a :: l)),
nth' (a :: l) n0 H0 = nth' (a' :: l') n0 (transport (lt n0) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n0 : nat) (H0 : n0 < length l),
nth' l n0 H0 = nth' l'0 n0 (transport (lt n0) p0 H0)) ->
l = l'0 n: nat Hn: n < length l
nth' (a :: l) n.+1 (leq_succ Hn) =
nth' l' n (transport (lt n) (path_nat_succ (length l) (length l') p) Hn)
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n0 : nat) (H0 : n0 < length (a :: l)),
nth' (a :: l) n0 H0 = nth' (a' :: l') n0 (transport (lt n0) p H0) IHl: forall (l'0 : list A) (p0 : length l = length l'0),
(forall (n0 : nat) (H0 : n0 < length l),
nth' l n0 H0 = nth' l'0 n0 (transport (lt n0) p0 H0)) ->
l = l'0 n: nat Hn: n < length l
nth' (a' :: l') n.+1 (transport (lt n.+1) p (leq_succ Hn)) =
nth' l' n (transport (lt n) (path_nat_succ (length l) (length l') p) Hn)
napply nth'_cons.Defined.(** The [nth n] element of a concatenated list [l ++ l'] where [n < length l] is the [nth] element of [l]. *)
A: Type l, l': list A n: nat H: n < length l
nth (l ++ l') n = nth l n
A: Type l, l': list A n: nat H: n < length l
nth (l ++ l') n = nth l n
A: Type l': list A n: nat H: n < length nil
nth (nil ++ l') n = nth nil n
A: Type a: A l, l': list A n: nat H: n < length (a :: l) IHl: forall (l'0 : list A) (n0 : nat),
n0 < length l -> nth (l ++ l'0) n0 = nth l n0
nth ((a :: l) ++ l') n = nth (a :: l) n
A: Type a: A l, l': list A n: nat H: n < length (a :: l) IHl: forall (l'0 : list A) (n0 : nat),
n0 < length l -> nth (l ++ l'0) n0 = nth l n0
nth ((a :: l) ++ l') n = nth (a :: l) n
A: Type a: A l, l': list A H: 0 < length (a :: l) IHl: forall (l'0 : list A) (n : nat), n < length l -> nth (l ++ l'0) n = nth l n
nth ((a :: l) ++ l') 0 = nth (a :: l) 0
A: Type a: A l, l': list A n: nat H: n.+1 < length (a :: l) IHl: forall (l'0 : list A) (n0 : nat),
n0 < length l -> nth (l ++ l'0) n0 = nth l n0
nth ((a :: l) ++ l') n.+1 = nth (a :: l) n.+1
A: Type a: A l, l': list A n: nat H: n.+1 < length (a :: l) IHl: forall (l'0 : list A) (n0 : nat),
n0 < length l -> nth (l ++ l'0) n0 = nth l n0
nth ((a :: l) ++ l') n.+1 = nth (a :: l) n.+1
byapply IHl, leq_pred'.Defined.(** The [nth i] element where [pred (length l) = i] is the last element of the list. *)
A: Type l: list A i: nat p: nat_pred (length l) = i
nth l i = last l
A: Type l: list A i: nat p: nat_pred (length l) = i
nth l i = last l
A: Type l: list A
nth l (nat_pred (length l)) = last l
A: Type
nth nil (nat_pred (length nil)) = last nil
A: Type a: A l: list A IHl: nth l (nat_pred (length l)) = last l
nth (a :: l) (nat_pred (length (a :: l))) = last (a :: l)
A: Type a: A l: list A IHl: nth l (nat_pred (length l)) = last l
nth (a :: l) (nat_pred (length (a :: l))) = last (a :: l)
A: Type a: A IHl: nth nil (nat_pred (length nil)) = last nil
nth [a] (nat_pred (length [a])) = last [a]
A: Type a, b: A l: list A IHl: nth (b :: l) (nat_pred (length (b :: l))) = last (b :: l)
nth (a :: b :: l) (nat_pred (length (a :: b :: l))) = last (a :: b :: l)
A: Type a, b: A l: list A IHl: nth (b :: l) (nat_pred (length (b :: l))) = last (b :: l)
nth (a :: b :: l) (nat_pred (length (a :: b :: l))) = last (a :: b :: l)
cbn; exact IHl.Defined.(** The last element of a list with an element appended is the appended element. *)
A: Type l: list A x: A
last (l ++ [x]) = Some x
A: Type l: list A x: A
last (l ++ [x]) = Some x
A: Type x: A
last (nil ++ [x]) = Some x
A: Type a: A l: list A x: A IHl: forallx0 : A, last (l ++ [x0]) = Some x0
last ((a :: l) ++ [x]) = Some x
A: Type a: A l: list A x: A IHl: forallx0 : A, last (l ++ [x0]) = Some x0
last ((a :: l) ++ [x]) = Some x
A: Type a, x: A IHl: forallx0 : A, last (nil ++ [x0]) = Some x0
last ([a] ++ [x]) = Some x
A: Type a, a0: A l: list A x: A IHl: forallx0 : A, last ((a0 :: l) ++ [x0]) = Some x0
last ((a :: a0 :: l) ++ [x]) = Some x
A: Type a, a0: A l: list A x: A IHl: forallx0 : A, last ((a0 :: l) ++ [x0]) = Some x0
last ((a :: a0 :: l) ++ [x]) = Some x
cbn; apply IHl.Defined.
A: Type l: list A a: A H: length l < length (l ++ [a])
nth' (l ++ [a]) (length l) H = a
A: Type l: list A a: A H: length l < length (l ++ [a])
nth' (l ++ [a]) (length l) H = a
A: Type a: A H: length nil < length (nil ++ [a])
nth' (nil ++ [a]) (length nil) H = a
A: Type l: list A IHl: forall (a0 : A) (H0 : length l < length (l ++ [a0])),
nth' (l ++ [a0]) (length l) H0 = a0 a', a: A H: length (a' :: l) < length ((a' :: l) ++ [a])
nth' ((a' :: l) ++ [a]) (length (a' :: l)) H = a
A: Type l: list A IHl: forall (a0 : A) (H0 : length l < length (l ++ [a0])),
nth' (l ++ [a0]) (length l) H0 = a0 a', a: A H: length (a' :: l) < length ((a' :: l) ++ [a])
nth' ((a' :: l) ++ [a]) (length (a' :: l)) H = a
apply IHl.Defined.(** ** Removing elements *)(** These functions allow surgery to be performed on a given list. *)(** *** Drop *)(** [drop n l] removes the first [n] elements of [l]. *)Fixpointdrop {A : Type} (n : nat) (l : list A) : list A :=
match n with
| 0 => l
| n.+1 => drop n (tail l)
end.(** A [drop] of zero elements is the identity, by definition. *)Definitiondrop_0 {A : Type} (l : list A) : drop 0 l = l := idpath.(** A [drop] of one element is the tail of the list, by definition. *)Definitiondrop_1 {A : Type} (l : list A) : drop 1 l = tail l := idpath.(** A [drop] of the empty list is the empty list. *)
A: Type n: nat
drop n nil = nil
A: Type n: nat
drop n nil = nil
byinduction n.Defined.(** A [drop] of [n] elements with [length l <= n] is the empty list. *)
A: Type n: nat l: list A H: length l <= n
drop n l = nil
A: Type n: nat l: list A H: length l <= n
drop n l = nil
A: Type n: nat H: length nil <= n
drop n nil = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n IHl: foralln0 : nat, length l <= n0 -> drop n0 l = nil
drop n (a :: l) = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n IHl: foralln0 : nat, length l <= n0 -> drop n0 l = nil
drop n (a :: l) = nil
A: Type a: A l: list A H: length (a :: l) <= 0 IHl: foralln : nat, length l <= n -> drop n l = nil
drop 0 (a :: l) = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln0 : nat, length l <= n0 -> drop n0 l = nil
drop n.+1 (a :: l) = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln0 : nat, length l <= n0 -> drop n0 l = nil
drop n.+1 (a :: l) = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln0 : nat, length l <= n0 -> drop n0 l = nil
length l <= n
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln0 : nat, length l <= n0 -> drop n0 l = nil
(length l).+1 <= n.+1
exact H.Defined.(** The length of a [drop n] is the length of the original list minus [n]. *)
A: Type n: nat l: list A
length (drop n l) = length l - n
A: Type n: nat l: list A
length (drop n l) = length l - n
A: Type n: nat
length (drop n nil) = length nil - n
A: Type n: nat a: A l: list A IHl: foralln0 : nat, length (drop n0 l) = length l - n0
length (drop n (a :: l)) = length (a :: l) - n
A: Type n: nat a: A l: list A IHl: foralln0 : nat, length (drop n0 l) = length l - n0
length (drop n (a :: l)) = length (a :: l) - n
A: Type a: A l: list A IHl: foralln : nat, length (drop n l) = length l - n
length (drop 0 (a :: l)) = length (a :: l) - 0
A: Type n: nat a: A l: list A IHl: foralln0 : nat, length (drop n0 l) = length l - n0
length (drop n.+1 (a :: l)) = length (a :: l) - n.+1
A: Type n: nat a: A l: list A IHl: foralln0 : nat, length (drop n0 l) = length l - n0
length (drop n.+1 (a :: l)) = length (a :: l) - n.+1
exact (IHl n).Defined.(** An element of a [drop] is an element of the original list. *)
A: Type n: nat l: list A x: A
InList x (drop n l) -> InList x l
A: Type n: nat l: list A x: A
InList x (drop n l) -> InList x l
A: Type n: nat l: list A x: A H: InList x (drop n l)
InList x l
A: Type n: nat x: A H: InList x (drop n nil)
InList x nil
A: Type n: nat a: A l: list A x: A H: InList x (drop n (a :: l)) IHl: forall (n0 : nat) (x0 : A), InList x0 (drop n0 l) -> InList x0 l
InList x (a :: l)
A: Type n: nat a: A l: list A x: A H: InList x (drop n (a :: l)) IHl: forall (n0 : nat) (x0 : A), InList x0 (drop n0 l) -> InList x0 l
InList x (a :: l)
A: Type a: A l: list A x: A H: InList x (drop 0 (a :: l)) IHl: forall (n : nat) (x0 : A), InList x0 (drop n l) -> InList x0 l
InList x (a :: l)
A: Type n: nat a: A l: list A x: A H: InList x (drop n.+1 (a :: l)) IHl: forall (n0 : nat) (x0 : A), InList x0 (drop n0 l) -> InList x0 l
InList x (a :: l)
A: Type n: nat a: A l: list A x: A H: InList x (drop n.+1 (a :: l)) IHl: forall (n0 : nat) (x0 : A), InList x0 (drop n0 l) -> InList x0 l
InList x (a :: l)
right; exact (IHl _ _ H).Defined.(** *** Take *)(** [take n l] keeps the first [n] elements of [l] and returns [l] if [n >= length l]. *)Fixpointtake {A : Type} (n : nat) (l : list A) : list A :=
match n, l with
| n.+1, x :: l => x :: take n l
| _, _ => nil
end.(** A [take] of zero elements is the empty list, by definition. *)Definitiontake_0 {A : Type} (l : list A) : take 0 l = nil := idpath.(** A [take] of the empty list is the empty list. *)
A: Type n: nat
take n nil = nil
A: Type n: nat
take n nil = nil
bydestruct n.Defined.(** A [take] of [n] elements with [length l <= n] is the original list. *)
A: Type n: nat l: list A H: length l <= n
take n l = l
A: Type n: nat l: list A H: length l <= n
take n l = l
A: Type n: nat H: length nil <= n
take n nil = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n IHl: foralln0 : nat, length l <= n0 -> take n0 l = l
take n (a :: l) = a :: l
A: Type n: nat a: A l: list A H: length (a :: l) <= n IHl: foralln0 : nat, length l <= n0 -> take n0 l = l
take n (a :: l) = a :: l
A: Type a: A l: list A H: length (a :: l) <= 0 IHl: foralln : nat, length l <= n -> take n l = l
take 0 (a :: l) = a :: l
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln0 : nat, length l <= n0 -> take n0 l = l
take n.+1 (a :: l) = a :: l
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln0 : nat, length l <= n0 -> take n0 l = l
take n.+1 (a :: l) = a :: l
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln0 : nat, length l <= n0 -> take n0 l = l
take n l = l
byapply IHl, leq_pred'.Defined.(** The length of a [take n] is the minimum of [n] and the length of the original list. *)
A: Type n: nat l: list A
length (take n l) = nat_min n (length l)
A: Type n: nat l: list A
length (take n l) = nat_min n (length l)
A: Type n: nat
length (take n nil) = nat_min n (length nil)
A: Type n: nat a: A l: list A IHl: foralln0 : nat, length (take n0 l) = nat_min n0 (length l)
length (take n (a :: l)) = nat_min n (length (a :: l))
A: Type n: nat
length (take n nil) = nat_min n (length nil)
A: Type n: nat
length nil = nat_min n (length nil)
A: Type n: nat
length nil = length nil
A: Type n: nat
length nil <= n
A: Type n: nat
length nil <= n
cbn; exact _.
A: Type n: nat a: A l: list A IHl: foralln0 : nat, length (take n0 l) = nat_min n0 (length l)
length (take n (a :: l)) = nat_min n (length (a :: l))
A: Type a: A l: list A IHl: foralln : nat, length (take n l) = nat_min n (length l)
length (take 0 (a :: l)) = nat_min 0 (length (a :: l))
A: Type n: nat a: A l: list A IHl: foralln0 : nat, length (take n0 l) = nat_min n0 (length l)
length (take n.+1 (a :: l)) = nat_min n.+1 (length (a :: l))
A: Type n: nat a: A l: list A IHl: foralln0 : nat, length (take n0 l) = nat_min n0 (length l)
length (take n.+1 (a :: l)) = nat_min n.+1 (length (a :: l))
cbn; f_ap.Defined.(** The length of a [take] is less than or equal to the length of the list. *)Definitionlength_take_leq {A : Type} {n : nat} (l : list A)
: length (take n l) <= length l
:= transport (funx => x <= length l) (length_take n l)^ (leq_nat_min_r _ _).(** An element of a [take] is an element of the original list. *)
A: Type n: nat l: list A x: A
InList x (take n l) -> InList x l
A: Type n: nat l: list A x: A
InList x (take n l) -> InList x l
A: Type n: nat l: list A x: A H: InList x (take n l)
InList x l
A: Type n: nat x: A H: InList x (take n nil)
InList x nil
A: Type n: nat a: A l: list A x: A H: InList x (take n (a :: l)) IHl: forall (n0 : nat) (x0 : A), InList x0 (take n0 l) -> InList x0 l
InList x (a :: l)
A: Type n: nat a: A l: list A x: A H: InList x (take n (a :: l)) IHl: forall (n0 : nat) (x0 : A), InList x0 (take n0 l) -> InList x0 l
InList x (a :: l)
A: Type a: A l: list A x: A H: InList x (take 0 (a :: l)) IHl: forall (n : nat) (x0 : A), InList x0 (take n l) -> InList x0 l
InList x (a :: l)
A: Type n: nat a: A l: list A x: A H: InList x (take n.+1 (a :: l)) IHl: forall (n0 : nat) (x0 : A), InList x0 (take n0 l) -> InList x0 l
InList x (a :: l)
A: Type a: A l: list A x: A H: InList x (take 0 (a :: l)) IHl: forall (n : nat) (x0 : A), InList x0 (take n l) -> InList x0 l
InList x (a :: l)
A: Type a: A l: list A x: A H: Empty IHl: forall (n : nat) (x0 : A), InList x0 (take n l) -> InList x0 l
InList x (a :: l)
contradiction.
A: Type n: nat a: A l: list A x: A H: InList x (take n.+1 (a :: l)) IHl: forall (n0 : nat) (x0 : A), InList x0 (take n0 l) -> InList x0 l
InList x (a :: l)
A: Type n: nat l: list A x: A IHl: forall (n0 : nat) (x0 : A), InList x0 (take n0 l) -> InList x0 l
InList x (x :: l)
A: Type n: nat a: A l: list A x: A H: InList x (take n l) IHl: forall (n0 : nat) (x0 : A), InList x0 (take n0 l) -> InList x0 l
InList x (a :: l)
A: Type n: nat l: list A x: A IHl: forall (n0 : nat) (x0 : A), InList x0 (take n0 l) -> InList x0 l
InList x (x :: l)
left; reflexivity.
A: Type n: nat a: A l: list A x: A H: InList x (take n l) IHl: forall (n0 : nat) (x0 : A), InList x0 (take n0 l) -> InList x0 l
InList x (a :: l)
right; exact (IHl _ _ H).Defined.(** Applying a [take] twice with [m] and [n] is the same as applying it once with [nat_min m n]. *)
A: Type m, n: nat l: list A
take n (take m l) = take (nat_min n m) l
A: Type m, n: nat l: list A
take n (take m l) = take (nat_min n m) l
A: Type m: nat l: list A
take 0 (take m l) = take (nat_min 0 m) l
A: Type m, n: nat l: list A IHn: forall (m0 : nat) (l0 : list A), take n (take m0 l0) = take (nat_min n m0) l0
take n.+1 (take m l) = take (nat_min n.+1 m) l
A: Type m, n: nat l: list A IHn: forall (m0 : nat) (l0 : list A), take n (take m0 l0) = take (nat_min n m0) l0
take n.+1 (take m l) = take (nat_min n.+1 m) l
A: Type n: nat l: list A IHn: forall (m : nat) (l0 : list A), take n (take m l0) = take (nat_min n m) l0
take n.+1 (take 0 l) = take (nat_min n.+10) l
A: Type m, n: nat l: list A IHn: forall (m0 : nat) (l0 : list A), take n (take m0 l0) = take (nat_min n m0) l0
take n.+1 (take m.+1 l) = take (nat_min n.+1 m.+1) l
A: Type m, n: nat l: list A IHn: forall (m0 : nat) (l0 : list A), take n (take m0 l0) = take (nat_min n m0) l0
take n.+1 (take m.+1 l) = take (nat_min n.+1 m.+1) l
A: Type m, n: nat IHn: forall (m0 : nat) (l : list A), take n (take m0 l) = take (nat_min n m0) l
take n.+1 (take m.+1 nil) = take (nat_min n.+1 m.+1) nil
A: Type m, n: nat a: A l': list A IHn: forall (m0 : nat) (l : list A), take n (take m0 l) = take (nat_min n m0) l
take n.+1 (take m.+1 (a :: l')) = take (nat_min n.+1 m.+1) (a :: l')
A: Type m, n: nat a: A l': list A IHn: forall (m0 : nat) (l : list A), take n (take m0 l) = take (nat_min n m0) l
take n.+1 (take m.+1 (a :: l')) = take (nat_min n.+1 m.+1) (a :: l')
A: Type m, n: nat a: A l': list A IHn: forall (m0 : nat) (l : list A), take n (take m0 l) = take (nat_min n m0) l
a :: take n (take m l') = a :: take (nat_min n m) l'
apply ap, IHn.Defined.(** [take] is commutative in [n]. *)
A: Type m, n: nat l: list A
take n (take m l) = take m (take n l)
A: Type m, n: nat l: list A
take n (take m l) = take m (take n l)
byrewrite !take_take_min, nat_min_comm.Defined.(** A [take n] does not change under concatenation if [n] is less than or equal to the length of the first list. *)
A: Type n: nat l1, l2: list A hn: n <= length l1
take n l1 = take n (l1 ++ l2)
A: Type n: nat l1, l2: list A hn: n <= length l1
take n l1 = take n (l1 ++ l2)
A: Type l1, l2: list A hn: 0 <= length l1
take 0 l1 = take 0 (l1 ++ l2)
A: Type n: nat l1, l2: list A hn: n.+1 <= length l1 IHn: foralll0l3 : list A, n <= length l0 -> take n l0 = take n (l0 ++ l3)
take n.+1 l1 = take n.+1 (l1 ++ l2)
A: Type l1, l2: list A hn: 0 <= length l1
take 0 l1 = take 0 (l1 ++ l2)
reflexivity.
A: Type n: nat l1, l2: list A hn: n.+1 <= length l1 IHn: foralll0l3 : list A, n <= length l0 -> take n l0 = take n (l0 ++ l3)
take n.+1 l1 = take n.+1 (l1 ++ l2)
A: Type n: nat l2: list A hn: n.+1 <= length nil IHn: foralll1l0 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l0)
take n.+1 nil = take n.+1 (nil ++ l2)
A: Type n: nat a: A l1, l2: list A hn: n.+1 <= length (a :: l1) IHn: foralll0l3 : list A, n <= length l0 -> take n l0 = take n (l0 ++ l3)
take n.+1 (a :: l1) = take n.+1 ((a :: l1) ++ l2)
A: Type n: nat l2: list A hn: n.+1 <= length nil IHn: foralll1l0 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l0)
take n.+1 nil = take n.+1 (nil ++ l2)
contradiction (not_lt_zero_r _ hn).
A: Type n: nat a: A l1, l2: list A hn: n.+1 <= length (a :: l1) IHn: foralll0l3 : list A, n <= length l0 -> take n l0 = take n (l0 ++ l3)
take n.+1 (a :: l1) = take n.+1 ((a :: l1) ++ l2)
A: Type n: nat a: A l1, l2: list A hn: n.+1 <= length (a :: l1) IHn: foralll0l3 : list A, n <= length l0 -> take n l0 = take n (l0 ++ l3)
a :: take n l1 = a :: take n (l1 ++ l2)
apply ap, IHn, leq_pred', hn.Defined.(** *** Remove *)(** [remove n l] removes the [n]-th element of [l]. *)Definitionremove {A : Type} (n : nat) (l : list A) : list A
:= take n l ++ drop n.+1 l.(** Removing the first element of a list is the tail of the list. *)Definitionremove_0 {A : Type} (l : list A) : remove 0 l = tail l := idpath.(** Removing the [n]-th element of a list with [length l <= n] is the original list. *)
A: Type n: nat l: list A H: length l <= n
remove n l = l
A: Type n: nat l: list A H: length l <= n
remove n l = l
A: Type n: nat l: list A H: length l <= n
take n l ++ drop n.+1 l = l
A: Type n: nat l: list A H: length l <= n
l ++ drop n.+1 l = l
A: Type n: nat l: list A H: length l <= n
length l <= n
A: Type n: nat l: list A H: length l <= n
l ++ drop n.+1 l = l
A: Type n: nat l: list A H: length l <= n
l ++ nil = l
A: Type n: nat l: list A H: length l <= n
length l <= n.+1
A: Type n: nat l: list A H: length l <= n
l ++ nil = l
apply app_nil.Defined.(** The length of a [remove n] is the length of the original list minus one. *)
A: Type n: nat l: list A H: n < length l
length (remove n l) = nat_pred (length l)
A: Type n: nat l: list A H: n < length l
length (remove n l) = nat_pred (length l)
A: Type n: nat l: list A H: n < length l
length (take n l ++ drop n.+1 l) = nat_pred (length l)
nat_min n (length l) + (length l - n.+1) = nat_pred (length l)
A: Type n: nat l: list A H: n < length l
n + (length l - n.+1) = nat_pred (length l)
A: Type n: nat l: list A H: n < length l
n <= length l
A: Type n: nat l: list A H: n < length l
n + (length l - n.+1) = nat_pred (length l)
A: Type n: nat l: list A H: n < length l
n + length l - n.+1 = nat_pred (length l)
A: Type n: nat l: list A H: n < length l
n.+1 <= length l
A: Type n: nat l: list A H: n < length l
n + length l - n.+1 = nat_pred (length l)
A: Type n: nat l: list A H: n < length l
nat_pred (n + length l - n) = nat_pred (length l)
A: Type n: nat l: list A H: n < length l
n + length l - n = length l
apply nat_add_sub_cancel_l.Defined.(** An element of a [remove] is an element of the original list. *)
A: Type n: nat l: list A x: A
InList x (remove n l) -> InList x l
A: Type n: nat l: list A x: A
InList x (remove n l) -> InList x l
A: Type n: nat l: list A x: A
InList x (take n l ++ drop n.+1 l) -> InList x l
A: Type n: nat l: list A x: A p: InList x (take n l ++ drop n.+1 l)
InList x l
A: Type n: nat l: list A x: A p: InList x (take n l) + InList x (drop n.+1 l)
InList x l
A: Type n: nat l: list A x: A
InList x (take n l) + InList x (drop n.+1 l) -> InList x l
A: Type n: nat l: list A x: A
InList x (take n l) -> InList x l
A: Type n: nat l: list A x: A
InList x (drop n.+1 l) -> InList x l
A: Type n: nat l: list A x: A
InList x (take n l) -> InList x l
apply take_inlist.
A: Type n: nat l: list A x: A
InList x (drop n.+1 l) -> InList x l
apply drop_inlist.Defined.(** *** Filter *)(** Produce the list of elements of a list that satisfy a decidable predicate. *)Fixpointlist_filter@{u v|} {A : Type@{u}} (l : list A) (P : A -> Type@{v})
(dec : forallx, 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.
A: Type l: list A P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A
InList x (list_filter l P dec) <-> InList x l * P x
A: Type l: list A P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A
InList x (list_filter l P dec) <-> InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A
InList x (list_filter nil P dec) <-> InList x nil * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
InList x (list_filter (a :: l) P dec) <-> InList x (a :: l) * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A
InList x (list_filter nil P dec) <-> InList x nil * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A
Empty <-> Empty * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A
Empty * P x <-> Empty
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A
Empty * P x <~> Empty
snapply prod_empty_l@{v}.
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
InList x (list_filter (a :: l) P dec) <-> InList x (a :: l) * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
InList x (if dec a then a :: list_filter l P dec else list_filter l P dec) <->
((a = x) + InList x l) * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
InList x (if dec a then a :: list_filter l P dec else list_filter l P dec) <->
?Goal
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
?Goal <-> ((a = x) + InList x l) * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
?Goal <-> ((a = x) + InList x l) * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
((a = x) + InList x l) * P x <-> ?Goal
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
((a = x) + InList x l) * P x <~> ?Goal
exact (sum_distrib_r@{k k k _ _ _ k k} _ _ _).
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A
InList x (if dec a then a :: list_filter l P dec else list_filter l P dec) <->
(a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
InList x (a :: list_filter l P dec) <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
InList x (list_filter l P dec) <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
InList x (a :: list_filter l P dec) <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
(a = x) + InList x (list_filter l P dec) <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
Type
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
(a = x) + InList x (list_filter l P dec) <-> ?B
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
?B <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
(a = x) + InList x (list_filter l P dec) <-> (a = x) + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
(a = x) + InList x l * P x <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
(a = x) + InList x l * P x <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
a = x -> (a = x) * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
(a = x) * P x -> a = x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
a = x -> (a = x) * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
(a = a) * P a
exact (idpath, p).
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: P a
(a = x) * P x -> a = x
exact fst.
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
InList x (list_filter l P dec) <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
InList x (list_filter l P dec) <-> ?Goal
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
?Goal <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
InList x l * P x <-> (a = x) * P x + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
(a = x) * P x + InList x l * P x <-> InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
(a = x) * P x + InList x l * P x <~> InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
(a = x) * P x + InList x l * P x <~> Empty + InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
(a = x) * P x <~> Empty
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
InList x l * P x <~> InList x l * P x
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
(a = x) * P x <~> Empty
A: Type P: A -> Type dec: forallx0 : A, Decidable (P x0) x: A l: list A IHl: InList x (list_filter l P dec) <-> InList x l * P x a: A p: ~ P a
(a = x) * P x -> Empty
byintros [[] r].Defined.
A: Type l, l': list A P: A -> Type dec: forallx : A, Decidable (P x)
list_filter (l ++ l') P dec = list_filter l P dec ++ list_filter l' P dec
A: Type l, l': list A P: A -> Type dec: forallx : A, Decidable (P x)
list_filter (l ++ l') P dec = list_filter l P dec ++ list_filter l' P dec
A: Type l': list A P: A -> Type dec: forallx : A, Decidable (P x)
list_filter (nil ++ l') P dec = list_filter nil P dec ++ list_filter l' P dec
A: Type l': list A P: A -> Type dec: forallx : A, Decidable (P x) l: list A IHl: list_filter (l ++ l') P dec = list_filter l P dec ++ list_filter l' P dec a: A
list_filter ((a :: l) ++ l') P dec =
list_filter (a :: l) P dec ++ list_filter l' P dec
A: Type l': list A P: A -> Type dec: forallx : A, Decidable (P x)
list_filter (nil ++ l') P dec = list_filter nil P dec ++ list_filter l' P dec
reflexivity.
A: Type l': list A P: A -> Type dec: forallx : A, Decidable (P x) l: list A IHl: list_filter (l ++ l') P dec = list_filter l P dec ++ list_filter l' P dec a: A
list_filter ((a :: l) ++ l') P dec =
list_filter (a :: l) P dec ++ list_filter l' P dec
A: Type l': list A P: A -> Type dec: forallx : A, Decidable (P x) l: list A IHl: list_filter (l ++ l') P dec = list_filter l P dec ++ list_filter l' P dec a: A p: P a
a :: list_filter (l ++ l') P dec =
(a :: list_filter l P dec) ++ list_filter l' P dec
simpl; f_ap.Defined.(** ** Sequences *)(** The length of a reverse sequence of [n] numbers is [n]. *)
n: nat
length (seq_rev n) = n
n: nat
length (seq_rev n) = n
length (seq_rev 0) = 0
n: nat IHn: length (seq_rev n) = n
length (seq_rev n.+1) = n.+1
n: nat IHn: length (seq_rev n) = n
length (seq_rev n.+1) = n.+1
cbn; f_ap.Defined.(** The length of a sequence of [n] numbers is [n]. *)
n: nat
length (seq n) = n
n: nat
length (seq n) = n
n: nat
length (seq_rev n) = n
apply length_seq_rev.Defined.(** The reversed sequence of [n.+1] numbers is the [n] followed by the rest of the reversed sequence. *)Definitionseq_rev_cons@{} (n : nat)
: seq_rev n.+1 = n :: seq_rev n
:= idpath.(** The sequence of [n.+1] numbers is the sequence of [n] numbers concatenated with [[n]]. *)
n: nat
seq n.+1 = seq n ++ [n]
n: nat
seq n.+1 = seq n ++ [n]
apply reverse_cons.Defined.(** Alternate definition of [seq_rev] that keeps the proofs of the entries being [< n]. *)
n: nat
list {k : nat & k < n}
n: nat
list {k : nat & k < n}
n: nat
foralln0 : nat, {k : nat & k < n0} -> {k : nat & k < n0.+1}
exact _.Defined.(** Alternate definition of [seq] that keeps the proofs of the entries being [< n]. *)Definitionseq'@{} (n : nat) : list {k : nat & k < n}
:= reverse (seq_rev' n).(** The length of [seq_rev' n] is [n]. *)
n: nat
length (seq_rev' n) = n
n: nat
length (seq_rev' n) = n
length (seq_rev' 0) = 0
n: nat IHn: length (seq_rev' n) = n
length (seq_rev' n.+1) = n.+1
n: nat IHn: length (seq_rev' n) = n
length (seq_rev' n.+1) = n.+1
n: nat IHn: length (seq_rev' n) = n
length
(list_map (functor_sigma idmap (fun (k : nat) (H : k < n) => leq_succ_r H))
(nat_rec (funn0 : nat => list {k : nat & k < n0}) nil
(fun (n0 : nat) (IHn0 : list {k : nat & k < n0}) =>
(n0; leq_refl n0.+1)
:: list_map
(functor_sigma idmap
(fun (k : nat) (H : k < n0) => leq_succ_r H))
IHn0)
n)) =
n
n: nat IHn: length (seq_rev' n) = n
length
(nat_rec (funn0 : nat => list {k : nat & k < n0}) nil
(fun (n0 : nat) (IHn0 : list {k : nat & k < n0}) =>
(n0; leq_refl n0.+1)
:: list_map
(functor_sigma idmap (fun (k : nat) (H : k < n0) => leq_succ_r H))
IHn0)
n) =
n
exact IHn.Defined.(** The length of [seq' n] is [n]. *)
n: nat
length (seq' n) = n
n: nat
length (seq' n) = n
n: nat
length (seq_rev' n) = n
apply length_seq_rev'.Defined.(** The [list_map] of first projections on [seq_rev' n] is [seq_rev n]. *)
apply seq_rev_seq_rev'.Defined.(** The [nth] element of a [seq_rev] is [n - i.+1]. *)
n, i: nat H: i < n
nth (seq_rev n) i = Some (n - i.+1)
n, i: nat H: i < n
nth (seq_rev n) i = Some (n - i.+1)
n: nat H: 0 < n
nth (seq_rev n) 0 = Some (n - 1)
n, i: nat H: i.+1 < n IHi: foralln0 : nat, i < n0 -> nth (seq_rev n0) i = Some (n0 - i.+1)
nth (seq_rev n) i.+1 = Some (n - i.+2)
n: nat H: 0 < n
nth (seq_rev n) 0 = Some (n - 1)
H: 0 < 0
nth (seq_rev 0) 0 = Some (0 - 1)
n: nat H: 0 < n.+1 IHn: 0 < n -> nth (seq_rev n) 0 = Some (n - 1)
nth (seq_rev n.+1) 0 = Some (n.+1 - 1)
n: nat H: 0 < n.+1 IHn: 0 < n -> nth (seq_rev n) 0 = Some (n - 1)
nth (seq_rev n.+1) 0 = Some (n.+1 - 1)
cbn; byrewrite nat_sub_zero_r.
n, i: nat H: i.+1 < n IHi: foralln0 : nat, i < n0 -> nth (seq_rev n0) i = Some (n0 - i.+1)
nth (seq_rev n) i.+1 = Some (n - i.+2)
i: nat H: i.+1 < 0 IHi: foralln : nat, i < n -> nth (seq_rev n) i = Some (n - i.+1)
nth (seq_rev 0) i.+1 = Some (0 - i.+2)
n, i: nat H: i.+1 < n.+1 IHi: foralln0 : nat, i < n0 -> nth (seq_rev n0) i = Some (n0 - i.+1) IHn: i.+1 < n -> nth (seq_rev n) i.+1 = Some (n - i.+2)
nth (seq_rev n.+1) i.+1 = Some (n.+1 - i.+2)
n, i: nat H: i.+1 < n.+1 IHi: foralln0 : nat, i < n0 -> nth (seq_rev n0) i = Some (n0 - i.+1) IHn: i.+1 < n -> nth (seq_rev n) i.+1 = Some (n - i.+2)
nth (seq_rev n.+1) i.+1 = Some (n.+1 - i.+2)
byapply IHi, leq_pred'.Defined.(** The [nth] element of a [seq] is [i]. *)
n, i: nat H: i < n
nth (seq n) i = Some i
n, i: nat H: i < n
nth (seq n) i = Some i
i: nat H: i < 0
nth (seq 0) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i
nth (seq n.+1) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i
nth (seq n.+1) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i
nth (seq n ++ [n]) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i H': i < n
nth (seq n ++ [n]) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i H': ~ (i < n)
nth (seq n ++ [n]) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i H': i < n
nth (seq n ++ [n]) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i H': i < n
i < length (seq n)
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i H': i < n
nth (seq n) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i H': i < n
nth (seq n) i = Some i
byapply IHn.
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i H': ~ (i < n)
nth (seq n ++ [n]) i = Some i
n, i: nat H: i < n.+1 IHn: i < n -> nth (seq n) i = Some i H': i >= n
nth (seq n ++ [n]) i = Some i
n, i: nat H: i <= n IHn: i < n -> nth (seq n) i = Some i H': i >= n
nth (seq n ++ [n]) i = Some i
i: nat H: i <= i IHn: i < i -> nth (seq i) i = Some i H': i >= i
nth (seq i ++ [i]) i = Some i
i: nat H: i <= i IHn: i < i -> nth (seq i) i = Some i H': i >= i
nat_pred (length (seq i ++ [i])) = i
i: nat H: i <= i IHn: i < i -> nth (seq i) i = Some i H': i >= i
last (seq i ++ [i]) = Some i
i: nat H: i <= i IHn: i < i -> nth (seq i) i = Some i H': i >= i
nat_pred (length (seq i ++ [i])) = i
i: nat H: i <= i IHn: i < i -> nth (seq i) i = Some i H': i >= i
nat_pred (length (seq i) + length [i]) = i
i: nat H: i <= i IHn: i < i -> nth (seq i) i = Some i H': i >= i
nat_pred (length [i] + length (seq i)) = i
apply length_seq.
i: nat H: i <= i IHn: i < i -> nth (seq i) i = Some i H': i >= i
last (seq i ++ [i]) = Some i
napply last_app.Defined.(** The [nth'] element of a [seq'] is [i]. *)
n, i: nat H: i < length (seq' n)
(nth' (seq' n) i H).1 = i
n, i: nat H: i < length (seq' n)
(nth' (seq' n) i H).1 = i
n, i: nat H: i < length (seq' n)
i < length (list_map pr1 (seq' n))
n, i: nat H: i < length (seq' n)
nth' (list_map pr1 (seq' n)) i ?Goal = i
n, i: nat H: i < length (seq' n)
nth' (list_map pr1 (seq' n)) i
(internal_paths_rew_r (funn0 : nat => i < n0) H
(length_list_map pr1 (seq' n))) =
i
n, i: nat H: i < length (seq' n)
list nat
n, i: nat H: i < length (seq' n)
list_map pr1 (seq' n) = ?Goal
n, i: nat H: i < length (seq' n)
nth' ?Goal i
(transport (funx : list nat => i < length x) ?Goal0
(internal_paths_rew_r (funn0 : nat => i < n0) H
(length_list_map pr1 (seq' n)))) =
i
n, i: nat H: i < length (seq' n)
nth' (seq n) i
(transport (funx : list nat => i < length x) (seq_seq' n)
(internal_paths_rew_r (funn0 : nat => i < n0) H
(length_list_map pr1 (seq' n)))) =
i
n, i: nat H: i < length (seq' n)
Some
(nth' (seq n) i
(transport (funx : list nat => i < length x)
(seq_seq' n)
(internal_paths_rew_r (funn0 : nat => i < n0) H
(length_list_map pr1 (seq' n))))) =
Some i
rapply equiv_iff_hprop.Defined.(** Turning a finite sequence into a list. *)DefinitionBuild_list {A : Type} (n : nat)
(f : forall (i : nat), (i < n) -> A)
: list A
:= list_map (fun '(i; Hi) => f i Hi) (seq' n).
A: Type n: nat f: foralli : nat, i < n -> A
length (Build_list n f) = n
A: Type n: nat f: foralli : nat, i < n -> A
length (Build_list n f) = n
A: Type n: nat f: foralli : nat, i < n -> A
length (seq' n) = n
apply length_seq'.Defined.
A: Type n: nat f: foralli0 : nat, i0 < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
nth' (Build_list n f) i Hi' = f i Hi
A: Type n: nat f: foralli0 : nat, i0 < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
nth' (Build_list n f) i Hi' = f i Hi
A: Type n: nat f: foralli0 : nat, i0 < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
length (seq' n) = n
A: Type n: nat f: foralli0 : nat, i0 < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
(letx := nth' (seq' n) i (transport (lt i) ?Goal^ Hi) inleti0 := x.1inletHi0 := x.2in f i0 Hi0) =
f i Hi
A: Type n: nat f: foralli0 : nat, i0 < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
(letx := nth' (seq' n) i (transport (lt i) (length_seq' n)^ Hi) inleti0 := x.1inletHi0 := x.2in f i0 Hi0) =
f i Hi
A: Type n: nat f: foralli0 : nat, i0 < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
(nth' (seq' n) i (transport (lt i) (length_seq' n)^ Hi)).1 = i
A: Type n: nat f: foralli0 : nat, i0 < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
transport (funi0 : nat => i0 < n) ?p
(nth' (seq' n) i (transport (lt i) (length_seq' n)^ Hi)).2 =
Hi
A: Type n: nat f: foralli0 : nat, i0 < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
transport (funi0 : nat => i0 < n)
(nth'_seq' n i (transport (lt i) (length_seq' n)^ Hi))
(nth' (seq' n) i (transport (lt i) (length_seq' n)^ Hi)).2 =
Hi
rapply path_ishprop.Defined.(** Restriction of an infinite sequence to a list of specified length. *)Definitionlist_restrict {A : Type} (s : nat -> A) (n : nat) : list A
:= Build_list n (funm_ => s m).Definitionlength_list_restrict {A : Type} (s : nat -> A) (n : nat)
: length (list_restrict s n) = n
:= length_Build_list _ _.(** [nth'] of the restriction of a sequence is the corresponding term of the sequence. *)
A: Type s: nat -> A n, i: nat Hi: i < length (list_restrict s n)
nth' (list_restrict s n) i Hi = s i
A: Type s: nat -> A n, i: nat Hi: i < length (list_restrict s n)
nth' (list_restrict s n) i Hi = s i
A: Type s: nat -> A n, i: nat Hi: i < length (list_restrict s n)
i < length (seq' n)
A: Type s: nat -> A n, i: nat Hi: i < length (list_restrict s n)
(letx := nth' (seq' n) i ?Goalinleti0 := x.1inletHi0 := x.2in s i0) =
s i
A: Type s: nat -> A n, i: nat Hi: i < length (list_restrict s n)
A: Type s: nat -> A n, i: nat Hi: i < length (list_restrict s n)
(letx :=
nth' (seq' n) i
(transport (lt i) (length_list_restrict s n @ (length_seq' n)^) Hi)
inleti0 := x.1inletHi0 := x.2in s i0) =
s i
exact (ap s (nth'_seq' _ _ _)).Defined.(** ** Repeat *)(** The length of a repeated list is the number of repetitions. *)
A: Type n: nat x: A
length (repeat x n) = n
A: Type n: nat x: A
length (repeat x n) = n
A: Type x: A
length (repeat x 0) = 0
A: Type n: nat x: A IHn: length (repeat x n) = n
length (repeat x n.+1) = n.+1
A: Type x: A
length (repeat x 0) = 0
reflexivity.
A: Type n: nat x: A IHn: length (repeat x n) = n
length (repeat x n.+1) = n.+1
exact (ap S IHn).Defined.(** An element of a repeated list is equal to the repeated element. *)
A: Type n: nat x, y: A
InList y (repeat x n) -> y = x
A: Type n: nat x, y: A
InList y (repeat x n) -> y = x
A: Type x, y: A
InList y (repeat x 0) -> y = x
A: Type n: nat x, y: A IHn: InList y (repeat x n) -> y = x
InList y (repeat x n.+1) -> y = x
A: Type n: nat x, y: A IHn: InList y (repeat x n) -> y = x
InList y (repeat x n.+1) -> y = x
A: Type n: nat x, y: A IHn: InList y (repeat x n) -> y = x p: x = y
y = x
A: Type n: nat x, y: A IHn: InList y (repeat x n) -> y = x i: InList y (repeat x n)
y = x
A: Type n: nat x, y: A IHn: InList y (repeat x n) -> y = x p: x = y
y = x
bysymmetry.
A: Type n: nat x, y: A IHn: InList y (repeat x n) -> y = x i: InList y (repeat x n)
y = x
byapply IHn.Defined.(** Restricting a sequence to [n.+1] terms has a computation rule. *)
A: Type s: nat -> A n: nat
list_restrict s n.+1 = list_restrict s n ++ [s n]
A: Type s: nat -> A n: nat
list_restrict s n.+1 = list_restrict s n ++ [s n]
A: Type s: nat -> A n: nat
list_map (funpat : {i : nat & i < n.+1} => s pat.1) (seq' n.+1) =
list_map (funpat : {i : nat & i < n} => s pat.1) (seq' n) ++ [s n]
A: Type s: nat -> A n: nat
list_map s (list_map (funx : {i : nat & i < n.+1} => x.1) (seq' n.+1)) =
list_map (funpat : {i : nat & i < n} => s pat.1) (seq' n) ++ [s n]
A: Type s: nat -> A n: nat
list_map s (seq n.+1) =
list_map (funpat : {i : nat & i < n} => s pat.1) (seq' n) ++ [s n]
A: Type s: nat -> A n: nat
list_map s (seq n ++ [n]) =
list_map (funpat : {i : nat & i < n} => s pat.1) (seq' n) ++ [s n]
A: Type s: nat -> A n: nat
list_map s (seq n) ++ list_map s [n] =
list_map (funpat : {i : nat & i < n} => s pat.1) (seq' n) ++ [s n]
A: Type s: nat -> A n: nat
list_map s (seq n) ++ [s n] =
list_map (funpat : {i : nat & i < n} => s pat.1) (seq' n) ++ [s n]
A: Type s: nat -> A n: nat
list_map s (seq n) =
list_map (funpat : {i : nat & i < n} => s pat.1) (seq' n)
A: Type s: nat -> A n: nat
list_map (funpat : {i : nat & i < n} => s pat.1) (seq' n) =
list_map s (seq n)
A: Type s: nat -> A n: nat
list_map s (list_map (funx : {i : nat & i < n} => x.1) (seq' n)) =
list_map s (seq n)
apply ap, seq_seq'.Defined.(** ** Forall *)(** If a predicate holds for all elements of a list, then the [for_all] predicate holds for the list. *)
A: Type P: A -> Type l: list A
(forallx : A, InList x l -> P x) -> for_all P l
A: Type P: A -> Type l: list A
(forallx : A, InList x l -> P x) -> for_all P l
A: Type P: A -> Type t: list A IHl: (forallx : A, InList x t -> P x) -> for_all P t h: A H: forallx : A, InList x (h :: t) -> P x
P h
A: Type P: A -> Type t: list A IHl: (forallx : A, InList x t -> P x) -> for_all P t h: A H: forallx : A, InList x (h :: t) -> P x
for_all P t
A: Type P: A -> Type t: list A IHl: (forallx : A, InList x t -> P x) -> for_all P t h: A H: forallx : A, InList x (h :: t) -> P x
P h
A: Type P: A -> Type t: list A IHl: (forallx : A, InList x t -> P x) -> for_all P t h: A H: forallx : A, InList x (h :: t) -> P x
InList h (h :: t)
byleft.
A: Type P: A -> Type t: list A IHl: (forallx : A, InList x t -> P x) -> for_all P t h: A H: forallx : A, InList x (h :: t) -> P x
for_all P t
A: Type P: A -> Type t: list A IHl: (forallx : A, InList x t -> P x) -> for_all P t h: A H: forallx : A, InList x (h :: t) -> P x
forallx : A, InList x t -> P x
A: Type P: A -> Type t: list A IHl: (forallx : A, InList x t -> P x) -> for_all P t h: A H: forallx : A, InList x (h :: t) -> P x y: A i: InList y t
P y
A: Type P: A -> Type t: list A IHl: (forallx : A, InList x t -> P x) -> for_all P t h: A H: forallx : A, InList x (h :: t) -> P x y: A i: InList y t
InList y (h :: t)
byright.Defined.(** Conversely, if [for_all P l] then each element of the list satisfies [P]. *)
A: Type P: A -> Type l: list A
for_all P l -> forallx : A, InList x l -> P x
A: Type P: A -> Type l: list A
for_all P l -> forallx : A, InList x l -> P x
A: Type P: A -> Type
for_all P nil -> forallx : A, InList x nil -> P x
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx0 : A, InList x0 l -> P x0 x: A
for_all P (x :: l) -> forallx0 : A, InList x0 (x :: l) -> P x0
A: Type P: A -> Type
for_all P nil -> forallx : A, InList x nil -> P x
contradiction.
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx0 : A, InList x0 l -> P x0 x: A
for_all P (x :: l) -> forallx0 : A, InList x0 (x :: l) -> P x0
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx : A, InList x l -> P x y: A Hx: P y Hl: for_all P l
P y
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx0 : A, InList x0 l -> P x0 x: A Hx: P x Hl: for_all P l y: A i: InList y l
P y
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx : A, InList x l -> P x y: A Hx: P y Hl: for_all P l
P y
exact Hx.
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx0 : A, InList x0 l -> P x0 x: A Hx: P x Hl: for_all P l y: A i: InList y l
P y
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx0 : A, InList x0 l -> P x0 x: A Hx: P x Hl: for_all P l y: A i: InList y l
for_all P l
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx0 : A, InList x0 l -> P x0 x: A Hx: P x Hl: for_all P l y: A i: InList y l
InList y l
A: Type P: A -> Type l: list A IHl: for_all P l -> forallx0 : A, InList x0 l -> P x0 x: A Hx: P x Hl: for_all P l y: A i: InList y l
InList y l
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)]. *)
A, B: Type P: A -> Type Q: B -> Type f: A -> B Hf: forallx : A, P x -> Q (f x)
foralll : list A, for_all P l -> for_all Q (list_map f l)
A, B: Type P: A -> Type Q: B -> Type f: A -> B Hf: forallx : A, P x -> Q (f x)
foralll : list A, for_all P l -> for_all Q (list_map f l)
A, B: Type P: A -> Type Q: B -> Type f: A -> B Hf: forallx0 : A, P x0 -> Q (f x0) l: list A IHl: for_all P l -> for_all Q (list_map f l) x: A
P x * for_all P l -> Q (f x) * for_all Q (list_map f l)
A, B: Type P: A -> Type Q: B -> Type f: A -> B Hf: forallx0 : A, P x0 -> Q (f x0) l: list A IHl: for_all P l -> for_all Q (list_map f l) x: A Hx: P x Hl: for_all P l
Q (f x) * for_all Q (list_map f l)
split; auto.Defined.(** A variant of [for_all_map P Q f] where [Q] is [P o f]. *)
A, B: Type P: B -> Type f: A -> B
foralll : list A, for_all (P o f) l -> for_all P (list_map f l)
A, B: Type P: B -> Type f: A -> B
foralll : list A, for_all (P o f) l -> for_all P (list_map f l)
byapply 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. *)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C Hdefl: foralll0 : list A, for_all P l0 -> for_all R (def_l l0) def_r: list B -> list C Hdefr: foralll0 : list B, for_all Q l0 -> for_all R (def_r l0) 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)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C Hdefl: foralll0 : list A, for_all P l0 -> for_all R (def_l l0) def_r: list B -> list C Hdefr: foralll0 : list B, for_all Q l0 -> for_all R (def_r l0) 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)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C Hdefl: foralll1 : list A, for_all P l1 -> for_all R (def_l l1) def_r: list B -> list C Hdefr: foralll0 : list B, for_all Q l0 -> for_all R (def_r l0) l2: list B
for_all P nil -> for_all Q l2 -> for_all R (list_map2 f def_l def_r nil l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C Hdefl: foralll0 : list A, for_all P l0 -> for_all R (def_l l0) def_r: list B -> list C Hdefr: foralll0 : list B, for_all Q l0 -> for_all R (def_r l0) l1: list A IHl1: foralll0 : list B,
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A l2: list B
for_all P (x :: l1) ->
for_all Q l2 -> for_all R (list_map2 f def_l def_r (x :: l1) l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C Hdefl: foralll1 : list A, for_all P l1 -> for_all R (def_l l1) def_r: list B -> list C Hdefr: foralll0 : list B, for_all Q l0 -> for_all R (def_r l0) l2: list B
for_all P nil -> for_all Q l2 -> for_all R (list_map2 f def_l def_r nil l2)
destruct l2 as [|y l2]; cbn; auto.
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C Hdefl: foralll0 : list A, for_all P l0 -> for_all R (def_l l0) def_r: list B -> list C Hdefr: foralll0 : list B, for_all Q l0 -> for_all R (def_r l0) l1: list A IHl1: foralll0 : list B,
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A l2: list B
for_all P (x :: l1) ->
for_all Q l2 -> for_all R (list_map2 f def_l def_r (x :: l1) l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C Hdefl: foralll0 : list A, for_all P l0 -> for_all R (def_l l0) def_r: list B -> list C Hdefr: foralll0 : list B, for_all Q l0 -> for_all R (def_r l0) l1: list A IHl1: foralll0 : list B,
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A l2: list B
P x * for_all P l1 ->
for_all Q l2 ->
for_all R
match l2 with
| nil => def_l (x :: l1)
| y :: l0 => f x y :: list_map2 f def_l def_r l1 l0
end
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C Hdefl: foralll0 : list A, for_all P l0 -> for_all R (def_l l0) def_r: list B -> list C Hdefr: foralll2 : list B, for_all Q l2 -> for_all R (def_r l2) l1: list A IHl1: foralll2 : list B,
for_all P l1 -> for_all Q l2 -> for_all R (list_map2 f def_l def_r l1 l2) x: A Hx: P x Hl1: for_all P l1
for_all R (def_l (x :: l1))
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C Hdefl: foralll0 : list A, for_all P l0 -> for_all R (def_l l0) def_r: list B -> list C Hdefr: foralll2 : list B, for_all Q l2 -> for_all R (def_r l2) l1: list A IHl1: foralll2 : list B,
for_all P l1 -> for_all Q l2 -> for_all R (list_map2 f def_l def_r l1 l2) x: A Hx: P x Hl1: for_all P l1
for_all P (x :: l1)
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. *)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C def_r: list B -> list C 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)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C def_r: list B -> list C 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)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C def_r: list B -> list C l2: list B p: length nil = length l2
for_all P nil -> for_all Q l2 -> for_all R (list_map2 f def_l def_r nil l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A l2: list B p: length (x :: l1) = length l2
for_all P (x :: l1) ->
for_all Q l2 -> for_all R (list_map2 f def_l def_r (x :: l1) l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C def_r: list B -> list C l2: list B p: length nil = length l2
for_all P nil -> for_all Q l2 -> for_all R (list_map2 f def_l def_r nil l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C def_r: list B -> list C p: length nil = length nil
for_all P nil -> for_all Q nil -> for_all R (list_map2 f def_l def_r nil nil)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C def_r: list B -> list C b: B l2: list B p: length nil = length (b :: l2)
for_all P nil ->
for_all Q (b :: l2) -> for_all R (list_map2 f def_l def_r nil (b :: l2))
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C def_r: list B -> list C p: length nil = length nil
for_all P nil -> for_all Q nil -> for_all R (list_map2 f def_l def_r nil nil)
reflexivity.
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x : A) (y : B), P x -> Q y -> R (f x y) def_l: list A -> list C def_r: list B -> list C b: B l2: list B p: length nil = length (b :: l2)
for_all P nil ->
for_all Q (b :: l2) -> for_all R (list_map2 f def_l def_r nil (b :: l2))
discriminate.
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A l2: list B p: length (x :: l1) = length l2
for_all P (x :: l1) ->
for_all Q l2 -> for_all R (list_map2 f def_l def_r (x :: l1) l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll2 : list B,
length l1 = length l2 ->
for_all P l1 -> for_all Q l2 -> for_all R (list_map2 f def_l def_r l1 l2) x: A p: length (x :: l1) = length nil
for_all P (x :: l1) ->
for_all Q nil -> for_all R (list_map2 f def_l def_r (x :: l1) nil)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2)
for_all P (x :: l1) ->
for_all Q (y :: l2) ->
for_all R (list_map2 f def_l def_r (x :: l1) (y :: l2))
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y : B), P x0 -> Q y -> R (f x0 y) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll2 : list B,
length l1 = length l2 ->
for_all P l1 -> for_all Q l2 -> for_all R (list_map2 f def_l def_r l1 l2) x: A p: length (x :: l1) = length nil
for_all P (x :: l1) ->
for_all Q nil -> for_all R (list_map2 f def_l def_r (x :: l1) nil)
discriminate.
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2)
for_all P (x :: l1) ->
for_all Q (y :: l2) ->
for_all R (list_map2 f def_l def_r (x :: l1) (y :: l2))
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2) Hx: P x Hl1: for_all P l1 Hy: Q y Hl2: for_all Q l2
for_all R (list_map2 f def_l def_r (x :: l1) (y :: l2))
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2) Hx: P x Hl1: for_all P l1 Hy: Q y Hl2: for_all Q l2
R (f x y)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2) Hx: P x Hl1: for_all P l1 Hy: Q y Hl2: for_all Q l2
for_all R (list_map2 f def_l def_r l1 l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2) Hx: P x Hl1: for_all P l1 Hy: Q y Hl2: for_all Q l2
R (f x y)
byapply Hf.
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2) Hx: P x Hl1: for_all P l1 Hy: Q y Hl2: for_all Q l2
for_all R (list_map2 f def_l def_r l1 l2)
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2) Hx: P x Hl1: for_all P l1 Hy: Q y Hl2: for_all Q l2
length l1 = length l2
A, B, C: Type P: A -> Type Q: B -> Type R: C -> Type f: A -> B -> C Hf: forall (x0 : A) (y0 : B), P x0 -> Q y0 -> R (f x0 y0) def_l: list A -> list C def_r: list B -> list C l1: list A IHl1: foralll0 : list B,
length l1 = length l0 ->
for_all P l1 -> for_all Q l0 -> for_all R (list_map2 f def_l def_r l1 l0) x: A y: B l2: list B p: length (x :: l1) = length (y :: l2) Hx: P x Hl1: for_all P l1 Hy: Q y Hl2: for_all Q l2
(length l1).+1 = (length l2).+1
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]. *)
A, B: Type P: A -> Type Q: B -> Type f: A -> B -> A Hf: forall (x : A) (y : B), 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)
A, B: Type P: A -> Type Q: B -> Type f: A -> B -> A Hf: forall (x : A) (y : B), 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)
A, B: Type P: A -> Type Q: B -> Type f: A -> B -> A Hf: forall (x : A) (y : B), P x -> Q y -> P (f x y) acc: A Ha: P acc Hl: for_all Q nil
P (fold_left f nil acc)
A, B: Type P: A -> Type Q: B -> Type f: A -> B -> A Hf: forall (x0 : A) (y : B), P x0 -> Q y -> P (f x0 y) l: list B IHl: forallacc0 : A, P acc0 -> for_all Q l -> P (fold_left f l acc0) x: B acc: A Ha: P acc Hl: for_all Q (x :: l)
P (fold_left f (x :: l) acc)
A, B: Type P: A -> Type Q: B -> Type f: A -> B -> A Hf: forall (x : A) (y : B), P x -> Q y -> P (f x y) acc: A Ha: P acc Hl: for_all Q nil
P (fold_left f nil acc)
exact Ha.
A, B: Type P: A -> Type Q: B -> Type f: A -> B -> A Hf: forall (x0 : A) (y : B), P x0 -> Q y -> P (f x0 y) l: list B IHl: forallacc0 : A, P acc0 -> for_all Q l -> P (fold_left f l acc0) x: B acc: A Ha: P acc Hl: for_all Q (x :: l)
P (fold_left f (x :: l) acc)
A, B: Type P: A -> Type Q: B -> Type f: A -> B -> A Hf: forall (x0 : A) (y : B), P x0 -> Q y -> P (f x0 y) l: list B IHl: forallacc0 : A, P acc0 -> for_all Q l -> P (fold_left f l acc0) x: B acc: A Ha: P acc Hl: for_all Q (x :: l)
P (fold_left f l (f acc x))
A, B: Type P: A -> Type Q: B -> Type f: A -> B -> A Hf: forall (x0 : A) (y : B), P x0 -> Q y -> P (f x0 y) l: list B IHl: forallacc0 : A, P acc0 -> for_all Q l -> P (fold_left f l acc0) x: B acc: A Ha: P acc Qx: Q x Hl: for_all Q l
P (fold_left f l (f acc x))
apply IHl; auto.Defined.(** [for_all] preserves the truncation predicate. *)
A: Type n: trunc_index P: A -> Type l: list A
for_all (funx : A => IsTrunc n (P x)) l -> IsTrunc n (for_all P l)
A: Type n: trunc_index P: A -> Type l: list A
for_all (funx : A => IsTrunc n (P x)) l -> IsTrunc n (for_all P l)
A: Type n: trunc_index P: A -> Type
Unit -> IsTrunc n Unit
A: Type n: trunc_index P: A -> Type x: A l: list A IHl: for_all (funx0 : A => IsTrunc n (P x0)) l -> IsTrunc n (for_all P l)
IsTrunc n (P x) * for_all (funx0 : A => IsTrunc n (P x0)) l ->
IsTrunc n (P x * for_all P l)
A: Type n: trunc_index P: A -> Type
Unit -> IsTrunc n Unit
destruct n; exact _.
A: Type n: trunc_index P: A -> Type x: A l: list A IHl: for_all (funx0 : A => IsTrunc n (P x0)) l -> IsTrunc n (for_all P l)
IsTrunc n (P x) * for_all (funx0 : A => IsTrunc n (P x0)) l ->
IsTrunc n (P x * for_all P l)
A: Type n: trunc_index P: A -> Type x: A l: list A IHl: for_all (funx0 : A => IsTrunc n (P x0)) l -> IsTrunc n (for_all P l) Hx: IsTrunc n (P x) Hl: for_all (funx0 : A => IsTrunc n (P x0)) l
IsTrunc n (P x * for_all P l)
A: Type n: trunc_index P: A -> Type x: A l: list A IHl: for_all (funx0 : A => IsTrunc n (P x0)) l -> IsTrunc n (for_all P l) Hx: IsTrunc n (P x) Hl: IsTrunc n (for_all P l)
IsTrunc n (P x * for_all P l)
exact _.Defined.
A: Type n: trunc_index P: A -> Type l: list A H: forallx : A, IsTrunc n (P x)
IsTrunc n (for_all P l)
A: Type n: trunc_index P: A -> Type l: list A H: forallx : A, IsTrunc n (P x)
IsTrunc n (for_all P l)
byapply 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. *)
A: Type n: nat P: A -> Type x: A
P x -> for_all P (repeat x n)
A: Type n: nat P: A -> Type x: A
P x -> for_all P (repeat x n)
A: Type n: nat P: A -> Type x: A H: P x
for_all P (repeat x n)
A: Type P: A -> Type x: A H: P x
for_all P (repeat x 0)
A: Type n: nat P: A -> Type x: A H: P x IHn: for_all P (repeat x n)
for_all P (repeat x n.+1)
A: Type n: nat P: A -> Type x: A H: P x IHn: for_all P (repeat x n)
for_all P (repeat x n.+1)
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. *)
A: Type P: A -> Type l: list A p: for_all P l
list {x : A & P x}
A: Type P: A -> Type l: list A p: for_all P l
list {x : A & P x}
A: Type P: A -> Type p: for_all P nil
list {x : A & P x}
A: Type P: A -> Type x: A l: list A p: for_all P (x :: l) IHl: for_all P l -> list {x0 : A & P x0}
list {x0 : A & P x0}
A: Type P: A -> Type x: A l: list A p: for_all P (x :: l) IHl: for_all P l -> list {x0 : A & P x0}
list {x0 : A & P x0}
A: Type P: A -> Type x: A l: list A Hx: P x Hl: for_all P l IHl: for_all P l -> list {x0 : A & P x0}
list {x0 : A & P x0}
exact ((x; Hx) :: IHl Hl).Defined.(** The length of a list of sigma types is the same as the original list. *)
A: Type P: A -> Type l: list A p: for_all P l
length (list_sigma P l p) = length l
A: Type P: A -> Type l: list A p: for_all P l
length (list_sigma P l p) = length l
A: Type P: A -> Type p: for_all P nil
length (list_sigma P nil p) = length nil
A: Type P: A -> Type l: list A IHl: forallp0 : for_all P l, length (list_sigma P l p0) = length l x: A p: for_all P (x :: l)
A: Type P: A -> Type l: list A IHl: forallp : for_all P l, length (list_sigma P l p) = length l x: A Hx: P x Hl: for_all P l
length
(list_rect A (funl0 : list A => for_all P l0 -> list {x0 : A & P x0})
(unit_name nil)
(fun (x0 : A) (l0 : list A)
(IHl0 : for_all P l0 -> list {x1 : A & P x1})
(p : P x0 * for_all P l0) =>
(x0; fst p) :: IHl0 (snd p))
l Hl) =
length l
apply IHl.Defined.(** If a predicate [P] is decidable then so is [for_all P]. *)
A: Type P: A -> Type H: forallx : A, Decidable (P x) l: list A
Decidable (for_all P l)
A: Type P: A -> Type H: forallx : A, Decidable (P x) l: list A
Decidable (for_all P l)
simple_list_induction l x l IHl; exact _.Defined.(** If a predicate [P] is decidable then so is [list_exists P]. *)
A: Type P: A -> Type H: forallx : A, Decidable (P x) l: list A
Decidable (list_exists P l)
A: Type P: A -> Type H: forallx : A, Decidable (P x) l: list A
Decidable (list_exists P l)
simple_list_induction l x l IHl; exact _.Defined.
A: Type P: A -> Type l: list A
list_exists P l -> {x : A & (InList x l * P x)%type}
A: Type P: A -> Type l: list A
list_exists P l -> {x : A & (InList x l * P x)%type}
A: Type P: A -> Type
list_exists P nil -> {x : A & (InList x nil * P x)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A
list_exists P (x :: l) -> {x0 : A & (InList x0 (x :: l) * P x0)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A
list_exists P (x :: l) -> {x0 : A & (InList x0 (x :: l) * P x0)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A
P x + list_exists P l -> {x0 : A & (((x = x0) + InList x0 l) * P x0)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A Px: P x
{x0 : A & (((x = x0) + InList x0 l) * P x0)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A ex: list_exists P l
{x0 : A & (((x = x0) + InList x0 l) * P x0)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A Px: P x
{x0 : A & (((x = x0) + InList x0 l) * P x0)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A Px: P x
((x = x) + InList x l) * P x
bysplit; [left|].
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A ex: list_exists P l
{x0 : A & (((x = x0) + InList x0 l) * P x0)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A ex: list_exists P l x': A H: InList x' l Px': P x'
{x0 : A & (((x = x0) + InList x0 l) * P x0)%type}
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x0 : A & (InList x0 l * P x0)%type} x: A ex: list_exists P l x': A H: InList x' l Px': P x'
((x = x') + InList x' l) * P x'
bysplit; [right|].Defined.
A: Type P: A -> Type l: list A
forallx : A, InList x l -> P x -> list_exists P l
A: Type P: A -> Type l: list A
forallx : A, InList x l -> P x -> list_exists P l
A: Type P: A -> Type
forallx : A, InList x nil -> P x -> list_exists P nil
A: Type P: A -> Type l: list A IHl: forallx0 : A, InList x0 l -> P x0 -> list_exists P l x: A
forallx0 : A, InList x0 (x :: l) -> P x0 -> list_exists P (x :: l)
A: Type P: A -> Type l: list A IHl: forallx0 : A, InList x0 l -> P x0 -> list_exists P l x: A
forallx0 : A, InList x0 (x :: l) -> P x0 -> list_exists P (x :: l)
A: Type P: A -> Type l: list A IHl: forallx0 : A, InList x0 l -> P x0 -> list_exists P l x, y: A p: P y
(x = y) + InList y l -> P x + list_exists P l
A: Type P: A -> Type l: list A IHl: forallx0 : A, InList x0 l -> P x0 -> list_exists P l x, y: A p: P y
x = y -> P x
A: Type P: A -> Type l: list A IHl: forallx0 : A, InList x0 l -> P x0 -> list_exists P l x, y: A p: P y
InList y l -> list_exists P l
A: Type P: A -> Type l: list A IHl: forallx0 : A, InList x0 l -> P x0 -> list_exists P l x, y: A p: P y
x = y -> P x
exact (funr => r^ # p).
A: Type P: A -> Type l: list A IHl: forallx0 : A, InList x0 l -> P x0 -> list_exists P l x, y: A p: P y
InList y l -> list_exists P l
A: Type P: A -> Type l: list A IHl: forallx0 : A, InList x0 l -> P x0 -> list_exists P l x, y: A p: P y H: InList y l
list_exists P l
byapply (IHl y).Defined.
n: nat P: nat -> Type H: forallk : nat, P k -> k < n
{k : nat & P k} <-> list_exists P (seq n)
n: nat P: nat -> Type H: forallk : nat, P k -> k < n
{k : nat & P k} <-> list_exists P (seq n)
n: nat P: nat -> Type H: forallk : nat, P k -> k < n
{k : nat & P k} -> list_exists P (seq n)
n: nat P: nat -> Type H: forallk : nat, P k -> k < n
list_exists P (seq n) -> {k : nat & P k}
n: nat P: nat -> Type H: forallk : nat, P k -> k < n
{k : nat & P k} -> list_exists P (seq n)
n: nat P: nat -> Type H: forallk0 : nat, P k0 -> k0 < n k: nat p: P k
list_exists P (seq n)
n: nat P: nat -> Type H: forallk0 : nat, P k0 -> k0 < n k: nat p: P k
InList k (seq n)
n: nat P: nat -> Type H: forallk0 : nat, P k0 -> k0 < n k: nat p: P k
P k
exact p.
n: nat P: nat -> Type H: forallk : nat, P k -> k < n
list_exists P (seq n) -> {k : nat & P k}
n: nat P: nat -> Type H: forallk : nat, P k -> k < n H1: list_exists P (seq n)
{k : nat & P k}
n: nat P: nat -> Type H: forallk : nat, P k -> k < n H1: {x : nat & (InList x (seq n) * P x)%type}
{k : nat & P k}
n: nat P: nat -> Type H: forallk0 : nat, P k0 -> k0 < n k: nat Hk: InList k (seq n) p: P k
{k0 : nat & P k0}
n: nat P: nat -> Type H: forallk0 : nat, P k0 -> k0 < n k: nat Hk: InList k (seq n) p: P k
P k
exact p.Defined.(** An upper bound on witnesses of a decidable predicate makes the sigma type decidable. *)
n: nat P: nat -> Type H1: forallk : nat, P k -> k < n H2: forallk : nat, Decidable (P k)
Decidable {k : nat & P k}
n: nat P: nat -> Type H1: forallk : nat, P k -> k < n H2: forallk : nat, Decidable (P k)
Decidable {k : nat & P k}
n: nat P: nat -> Type H1: forallk : nat, P k -> k < n H2: forallk : nat, Decidable (P k)
?Goal <-> {k : nat & P k}
n: nat P: nat -> Type H1: forallk : nat, P k -> k < n H2: forallk : nat, Decidable (P k)
Decidable ?Goal
n: nat P: nat -> Type H1: forallk : nat, P k -> k < n H2: forallk : nat, Decidable (P k)
forallk : nat, P k -> k < ?Goal0
n: nat P: nat -> Type H1: forallk : nat, P k -> k < n H2: forallk : nat, Decidable (P k)
Decidable (list_exists P (seq ?Goal0))
n: nat P: nat -> Type H1: forallk : nat, P k -> k < n H2: forallk : nat, Decidable (P k)
Decidable (list_exists P (seq n))
exact _.Defined.(** A common special case. See also [decidable_search] in Misc/BoundedSearch.v for a similar result with different dependencies. *)Definitiondecidable_exists_bounded_nat (n : nat) (P : nat -> Type)
(H2 : forallk, Decidable (P k))
: Decidable { k : nat & prod (k < n) (P k) }
:= decidable_exists_nat n _ (funk => fst) _.