Built with Alectryon, running Coq+SerAPI v8.19.0+0.19.3. 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.
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
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: forallxyz : 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
(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: forallxyz : 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
(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: forallxyz : 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
(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: forallxyz : 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
(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: forallxyz : 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
(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: forallxyz : 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
(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: forallxyz : 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
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: forallxyz : 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
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: forallxyz : 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
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: forallxyz : 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
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: forallxyz : 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
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: forallxyz : 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
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: forallxyz : 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
ap (funx : list A => (a :: x) ++ 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: foralli : A, fold_left f (l ++ l') i = fold_left f l' (fold_left f l i)
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: foralli : A, fold_left f (l ++ l') i = fold_left f l' (fold_left f l i)
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: foralli : A, fold_right f i (l ++ l') = fold_right f (fold_right f i 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: foralli : A, fold_right f i (l ++ l') = fold_right f (fold_right f i 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) -> {y : A & ((f y = x) * InList y 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) -> {y : A & ((f y = x) * InList y 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) -> {y : A & ((f y = x) * InList y 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) -> {y : A & ((f y = x) * InList y 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) -> {y : A & ((f y = x) * InList y 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) -> {y : A & ((f y = x) * InList y 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) -> {y : A & ((f y = x) * InList y 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: (forallx : A, InList x l -> f x = x) -> 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: (forallx : A, InList x l -> f x = x) -> 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: (forallx : A, InList x l -> f x = x) -> 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: (forallx : A, InList x l -> f x = x) -> 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: (forallx : A, InList x l -> f x = x) -> 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: (forallx : A, InList x l -> f x = x) -> 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: (forallx : A, InList x l -> f x = x) -> 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: (forallx : A, InList x l -> f x = x) -> list_map f l = l
forallx : A, InList x 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: (forallx : A, InList x l -> f x = x) -> 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: (forallx : A, InList x l -> f x = x) -> 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: 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 l2: list B p: length (x :: l1) = length l2 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 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: 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 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: 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: foralll2 : list B,
length l1 = length l2 ->
length (list_map2 f defl defr l1 l2) =
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 (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}}
{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 (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}}
{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) (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}}
{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 (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}}
{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 (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}}
{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 (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}}
{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 (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}}
{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 (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}}
{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 (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}}
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 (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}} 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 (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}} 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 (funx : A => f x y) l
list_map2 f defl defr (x :: l)
(repeat y (length (x :: l))) =
list_map (funx : A => f x 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 (funx : A => f x y) l
list_map2 f defl defr (x :: l)
(repeat y (length (x :: l))) =
list_map (funx : A => f x 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' : list A, reverse (l ++ l') = reverse l' ++ 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: foralln : nat, n < length l -> {x : A & nth l n = 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: foralln : nat, n < length l -> {x : A & nth l n = 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: foralln : nat, n < length l -> {x : A & nth l n = 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: foralln : nat, n < length l -> {x : A & nth l n = 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: foralln : nat, n < length l -> {x : A & nth l n = Some x}
n < length l
A: Type a: A l: list A n: nat H: n.+1 < length (a :: l) IHa: foralln : nat, n < length l -> {x : A & nth l n = 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 (n : nat) (H : n < length l), InList (nth' l n H) 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 (n : nat) (H : n < length l), InList (nth' l n H) 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) (H : n < length l), InList (nth' l n H) 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 (n : nat) (H : n < length l), InList (nth' l n H) 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 (n : nat) (H : n < length l), InList (nth' l n H) 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 (n : nat) (H : n < length l), InList (nth' l n H) 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' : list A) (n : nat) (H : n < length l)
(H' : n < length (l ++ l')), nth' (l ++ l') n H' = nth' l n H
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' : list A) (n : nat) (H : n < length l)
(H' : n < length (l ++ l')), nth' (l ++ l') n H' = nth' l n H
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' : list A) (n : nat) (H : n < length l)
(H' : n < length (l ++ l')), nth' (l ++ l') n H' = nth' l n H
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' : list A) (n : nat) (H : n < length l)
(H' : n < length (l ++ l')), nth' (l ++ l') n H' = nth' l n H
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' : list A) (n : nat) (H : n < length l)
(H' : n < length (l ++ l')), nth' (l ++ l') n H' = nth' l n H
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 (A : Type) (l : list A) {struct l} :
nat :=
match l with
| nil => 0
| _ :: l0 => (length A l0).+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 -> {n : nat & {H : n < length l & nth' l n H = x}} i: InList x l n: nat H: n < length l H': nth' l n H = 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 l H': nth' l n H = x
(funn : nat =>
{H : n < length (a :: l) & nth' (a :: l) n H = x})
n.+1
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 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 -> {n : nat & {H : n < length l & nth' l n H = 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 -> {n : nat & {H : n < length l & nth' l n H = 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 -> {n : nat & {H : n < length l & nth' l n H = 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: foralln : nat, nth (list_map f l) n = functor_option f (nth l n)
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: foralln : nat, nth (list_map f l) n = functor_option f (nth l n)
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: foralln : nat, nth (list_map f l) n = functor_option f (nth l n)
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: foralln : nat, nth (list_map f l) n = functor_option f (nth l n)
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 (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)
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 (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)
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) (H : n < length l) (H' : n < length (list_map f l)),
nth' (list_map f l) n H' = f (nth' l n H)
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 (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)
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 (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)
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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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) (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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) (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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) (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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
(A B C : Type) (f : A -> B -> C)
(def_l : list A -> list C)
(def_r : list B -> list C)
(l1 : list A) (l2 : list B) {struct l1} :
list C :=
match l1 with
| nil =>
match l2 with
| nil => nil
| _ :: _ => def_r l2
end
| x :: l3 =>
match l2 with
| nil => def_l l1
| y :: l4 =>
f x y
:: list_map2 A B C f def_l def_r l3 l4
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 (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)),
length l1 = length l2 ->
f (nth' l1 n H) (nth' l2 n H') =
nth' (list_map2 f defl defr l1 l2) n H'' 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 (i : nat) (H : i < length (repeat x n)), nth' (repeat x n) i H = 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 (i : nat) (H : i < length (repeat x n)), nth' (repeat x n) i H = 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) (H : i < length (repeat x n)), nth' (repeat x n) i H = 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 (i : nat) (H : i < length (repeat x n)), nth' (repeat x n) i H = 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 (i : nat) (H : i < length (repeat x n)), nth' (repeat x n) i H = 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) (H : n < length l),
nth' l n H = nth' l' n (transport (lt n) p H)
l = l'
A: Type l': list A p: length nil = length l' H: forall (n : nat) (H : n < length nil),
nth' nil n H = nth' l' n (transport (lt n) p H)
nil = l'
A: Type a: A l, l': list A p: length (a :: l) = length l' H: forall (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' l' n (transport (lt n) p H) IHl: forall (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 :: l = l'
A: Type l': list A p: length nil = length l' H: forall (n : nat) (H : n < length nil),
nth' nil n H = nth' l' n (transport (lt n) p H)
nil = l'
A: Type p: length nil = length nil H: forall (n : nat) (H : n < length nil),
nth' nil n H = nth' nil n (transport (lt n) p H)
nil = nil
A: Type a: A l': list A p: length nil = length (a :: l') H: forall (n : nat) (H : n < length nil),
nth' nil n H =
nth' (a :: l') n (transport (lt n) p H)
nil = a :: l'
A: Type p: length nil = length nil H: forall (n : nat) (H : n < length nil),
nth' nil n H = nth' nil n (transport (lt n) p H)
nil = nil
reflexivity.
A: Type a: A l': list A p: length nil = length (a :: l') H: forall (n : nat) (H : n < length nil),
nth' nil n H =
nth' (a :: l') n (transport (lt n) p H)
nil = a :: l'
discriminate.
A: Type a: A l, l': list A p: length (a :: l) = length l' H: forall (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' l' n (transport (lt n) p H) IHl: forall (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 :: l = l'
A: Type a: A l: list A p: length (a :: l) = length nil H: forall (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' nil n (transport (lt n) p H) IHl: forall (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 :: 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) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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 :: 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) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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 :: 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) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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 = a'
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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'
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) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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 = 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) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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'
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) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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'
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) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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'
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) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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'
forall (n : nat) (H : n < length l),
nth' l n H =
nth' l' n
(transport (lt n)
(path_nat_succ (length l) (length l') p) H)
A: Type a: A l: list A a': A l': list A p: length (a :: l) = length (a' :: l') H: forall (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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' 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 (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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' 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 (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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' 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 (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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' 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 (n : nat) (H : n < length (a :: l)),
nth' (a :: l) n H =
nth' (a' :: l') n (transport (lt n) p H) IHl: forall (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' 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' : list A) (n : nat), n < length l -> nth (l ++ l') n = nth l n
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' : list A) (n : nat), n < length l -> nth (l ++ l') n = nth l n
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' : list A) (n : nat), n < length l -> nth (l ++ l') 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' : list A) (n : nat), n < length l -> nth (l ++ l') n = nth l n
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' : list A) (n : nat), n < length l -> nth (l ++ l') n = nth l n
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: forallx : A, last (l ++ [x]) = Some x
last ((a :: l) ++ [x]) = Some x
A: Type a: A l: list A x: A IHl: forallx : A, last (l ++ [x]) = Some x
last ((a :: l) ++ [x]) = Some x
A: Type a, x: A IHl: forallx : A, last (nil ++ [x]) = Some x
last ([a] ++ [x]) = Some x
A: Type a, a0: A l: list A x: A IHl: forallx : A, last ((a0 :: l) ++ [x]) = Some x
last ((a :: a0 :: l) ++ [x]) = Some x
A: Type a, a0: A l: list A x: A IHl: forallx : A, last ((a0 :: l) ++ [x]) = Some x
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 (a : A) (H : length l < length (l ++ [a])),
nth' (l ++ [a]) (length l) H = a 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 (a : A) (H : length l < length (l ++ [a])),
nth' (l ++ [a]) (length l) H = a 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: foralln : nat, length l <= n -> drop n l = nil
drop n (a :: l) = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n IHl: foralln : nat, length l <= n -> drop n 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: foralln : nat, length l <= n -> drop n l = nil
drop n.+1 (a :: l) = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln : nat, length l <= n -> drop n l = nil
drop n.+1 (a :: l) = nil
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln : nat, length l <= n -> drop n l = nil
length l <= n
A: Type n: nat a: A l: list A H: length (a :: l) <= n.+1 IHl: foralln : nat, length l <= n -> drop n 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: foralln : nat, length (drop n l) = length l - n
length (drop n (a :: l)) = length (a :: l) - n
A: Type n: nat a: A l: list A IHl: foralln : nat, length (drop n l) = length l - n
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: foralln : nat, length (drop n l) = length l - n
length (drop n.+1 (a :: l)) = length (a :: l) - n.+1
A: Type n: nat a: A l: list A IHl: foralln : nat, length (drop n l) = length l - n
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 (n : nat) (x : A), InList x (drop n l) -> InList x 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 (n : nat) (x : A), InList x (drop n l) -> InList x 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) (x : A), InList x (drop n l) -> InList x 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 (n : nat) (x : A), InList x (drop n l) -> InList x 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 (n : nat) (x : A), InList x (drop n l) -> InList x 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: foralln : nat, length l <= n -> take n l = l
take n (a :: l) = a :: l
A: Type n: nat a: A l: list A H: length (a :: l) <= n IHl: foralln : nat, length l <= n -> take n 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: foralln : nat, length l <= n -> take n 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: foralln : nat, length l <= n -> take n 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: foralln : nat, length l <= n -> take n 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: foralln : nat, length (take n l) = nat_min n (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: foralln : nat, length (take n l) = nat_min n (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: foralln : nat, length (take n l) = nat_min n (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: foralln : nat, length (take n l) = nat_min n (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 (n : nat) (x : A), InList x (take n l) -> InList x 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 (n : nat) (x : A), InList x (take n l) -> InList x 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) (x : A), InList x (take n l) -> InList x 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 (n : nat) (x : A), InList x (take n l) -> InList x 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) (x : A), InList x (take n l) -> InList x l
InList x (a :: l)
A: Type a: A l: list A x: A H: Empty IHl: forall (n : nat) (x : A), InList x (take n l) -> InList x 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 (n : nat) (x : A), InList x (take n l) -> InList x l
InList x (a :: l)
A: Type n: nat l: list A x: A IHl: forall (n : nat) (x : A), InList x (take n l) -> InList x l
InList x (x :: l)
A: Type n: nat a: A l: list A x: A H: InList x (take n l) IHl: forall (n : nat) (x : A), InList x (take n l) -> InList x l
InList x (a :: l)
A: Type n: nat l: list A x: A IHl: forall (n : nat) (x : A), InList x (take n l) -> InList x 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 (n : nat) (x : A), InList x (take n l) -> InList x 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 (m : nat) (l : list A), take n (take m l) = take (nat_min n m) l
take n.+1 (take m l) = take (nat_min n.+1 m) l
A: Type m, n: nat l: list A IHn: forall (m : nat) (l : list A), take n (take m l) = take (nat_min n m) l
take n.+1 (take m l) = take (nat_min n.+1 m) l
A: Type n: nat l: list A IHn: forall (m : nat) (l : list A), take n (take m l) = take (nat_min n m) l
take n.+1 (take 0 l) = take (nat_min n.+10) l
A: Type m, n: nat l: list A IHn: forall (m : nat) (l : list A), take n (take m l) = take (nat_min n m) l
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 (m : nat) (l : list A), take n (take m l) = take (nat_min n m) l
take n.+1 (take m.+1 l) = take (nat_min n.+1 m.+1) l
A: Type m, n: nat IHn: forall (m : nat) (l : list A), take n (take m l) = take (nat_min n m) 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 (m : nat) (l : list A), take n (take m l) = take (nat_min n m) 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 (m : nat) (l : list A), take n (take m l) = take (nat_min n m) 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 (m : nat) (l : list A), take n (take m l) = take (nat_min n m) 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: foralll1l2 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l2)
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: foralll1l2 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l2)
take n.+1 l1 = take n.+1 (l1 ++ l2)
A: Type n: nat l2: list A hn: n.+1 <= length nil IHn: foralll1l2 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l2)
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: foralll1l2 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l2)
take n.+1 (a :: l1) = take n.+1 ((a :: l1) ++ l2)
A: Type n: nat l2: list A hn: n.+1 <= length nil IHn: foralll1l2 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l2)
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: foralll1l2 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l2)
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: foralll1l2 : list A, n <= length l1 -> take n l1 = take n (l1 ++ l2)
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))%type
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: forallx : A, Decidable (P x) x: A
InList x (list_filter l P dec) <-> InList x l * P x
A: Type l: list A P: A -> Type dec: forallx : A, Decidable (P x) x: A
InList x (list_filter l P dec) <-> InList x l * P x
A: Type P: A -> Type dec: forallx : A, Decidable (P x) x: A
InList x (list_filter nil P dec) <->
InList x nil * P x
A: Type P: A -> Type dec: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) x: A
InList x (list_filter nil P dec) <->
InList x nil * P x
A: Type P: A -> Type dec: forallx : A, Decidable (P x) x: A
Empty <-> Empty * P x
A: Type P: A -> Type dec: forallx : A, Decidable (P x) x: A
Empty * P x <-> Empty
A: Type P: A -> Type dec: forallx : A, Decidable (P x) x: A
Empty * P x <~> Empty
snapply prod_empty_l@{v}.
A: Type P: A -> Type dec: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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)%type
exact (idpath, p).
A: Type P: A -> Type dec: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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: forallx : A, Decidable (P x) 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
foralln : nat,
{k : nat & k < n} -> {k : nat & k < n.+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 (funn : nat => list {k : nat & k < n})
nil
(fun (n : nat) (IHn : list {k : nat & k < n})
=>
(n; leq_refl n.+1)
:: list_map
(functor_sigma idmap
(fun (k : nat) (H : k < n) =>
leq_succ_r H)) IHn) n)) = n
n: nat IHn: length (seq_rev' n) = n
length
(nat_rec (funn : nat => list {k : nat & k < n}) nil
(fun (n : nat) (IHn : list {k : nat & k < n}) =>
(n; leq_refl n.+1)
:: list_map
(functor_sigma idmap
(fun (k : nat) (H : k < n) =>
leq_succ_r H)) IHn) 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: foralln : nat, i < n -> nth (seq_rev n) i = Some (n - 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: foralln : nat, i < n -> nth (seq_rev n) i = Some (n - 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: foralln : nat, i < n -> nth (seq_rev n) i = Some (n - 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: foralln : nat, i < n -> nth (seq_rev n) i = Some (n - 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 (funn : nat => i < n) 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 (funn : nat => i < n) 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 (funn : nat => i < n) 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 (funn : nat => i < n) 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: foralli : nat, i < 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: foralli : nat, i < 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: foralli : nat, i < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
length (seq' n) = n
A: Type n: nat f: foralli : nat, i < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
(letx := nth' (seq' n) i (transport (lt i) ?Goal^ Hi)
inleti := x.1inletHi := x.2in f i Hi) = f i Hi
A: Type n: nat f: foralli : nat, i < 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) inleti := x.1inletHi := x.2in f i Hi) = f i Hi
A: Type n: nat f: foralli : nat, i < 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: foralli : nat, i < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
transport (funi : nat => i < n) ?p
(nth' (seq' n) i
(transport (lt i) (length_seq' n)^ Hi)).2 = Hi
A: Type n: nat f: foralli : nat, i < n -> A i: nat Hi: i < n Hi': i < length (Build_list n f)
transport (funi : nat => i < 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 ?Goalinleti := x.1inletHi := x.2in s i) = 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) inleti := x.1inletHi := x.2in s i) = 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 -> forallx : A, InList x l -> P x 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 -> forallx : A, InList x l -> P x 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 -> forallx : A, InList x l -> P x 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 -> forallx : A, InList x l -> P x 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 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 -> forallx : A, InList x l -> P x 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 -> forallx : A, InList x l -> P x 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: forallx : A, P x -> Q (f x) 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: forallx : A, P x -> Q (f x) 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))%type
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: foralll1 : list A,
for_all P l1 -> for_all R (def_l l1) def_r: list B -> list C Hdefr: foralll2 : list B,
for_all Q l2 -> for_all R (def_r l2) l1: list A l2: list B
for_all P l1 ->
for_all Q l2 ->
for_all R (list_map2 f def_l def_r l1 l2)
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: foralll2 : list B,
for_all Q l2 -> for_all R (def_r l2) l1: list A l2: list B
for_all P l1 ->
for_all Q l2 ->
for_all R (list_map2 f def_l def_r l1 l2)
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: foralll2 : list B,
for_all Q l2 -> for_all R (def_r l2) 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 (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: 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 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: foralll2 : list B,
for_all Q l2 -> for_all R (def_r l2) 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 (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: 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 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: 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 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 :: l2 => f x y :: list_map2 f def_l def_r l1 l2
end
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: 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 (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: 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 (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 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 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 (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 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 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 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 (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 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 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 (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 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 (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 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 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 (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 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 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 (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 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 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 (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 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 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 (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 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 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 (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 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 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 (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 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 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 (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 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 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 (x : A) (y : B), P x -> Q y -> P (f x y) l: list B IHl: forallacc : A, P acc -> for_all Q l -> P (fold_left f l acc) 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 (x : A) (y : B), P x -> Q y -> P (f x y) l: list B IHl: forallacc : A, P acc -> for_all Q l -> P (fold_left f l acc) 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) l: list B IHl: forallacc : A, P acc -> for_all Q l -> P (fold_left f l acc) 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 (x : A) (y : B), P x -> Q y -> P (f x y) l: list B IHl: forallacc : A, P acc -> for_all Q l -> P (fold_left f l acc) 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 (funx : A => IsTrunc n (P x)) l -> IsTrunc n (for_all P l)
IsTrunc n (P x) *
for_all (funx : A => IsTrunc n (P x)) 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 (funx : A => IsTrunc n (P x)) l -> IsTrunc n (for_all P l)
IsTrunc n (P x) *
for_all (funx : A => IsTrunc n (P x)) 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 (funx : A => IsTrunc n (P x)) l -> IsTrunc n (for_all P l) Hx: IsTrunc n (P x) Hl: for_all (funx : A => IsTrunc n (P x)) 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 (funx : A => IsTrunc n (P x)) 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 {x : A & P x}
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 {x : A & P x}
list {x : A & P x}
A: Type P: A -> Type x: A l: list A Hx: P x Hl: for_all P l IHl: for_all P l -> list {x : A & P x}
list {x : A & P x}
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: forallp : for_all P l, length (list_sigma P l p) = 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
(funl : list A =>
for_all P l -> list {x : A & P x})
(unit_name nil)
(fun (x : A) (l : list A)
(IHl : for_all P l -> list {x0 : A & P x0})
(p : P x * for_all P l) =>
(x; fst p) :: IHl (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 -> {x : A & (InList x l * P x)%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 -> {x : A & (InList x l * P x)%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 -> {x : A & (InList x l * P x)%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 -> {x : A & (InList x l * P x)%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 -> {x : A & (InList x l * P x)%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 -> {x : A & (InList x l * P x)%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 -> {x : A & (InList x l * P x)%type} x: A Px: P x
(((x = x) + InList x l) * P x)%type
bysplit; [left|].
A: Type P: A -> Type l: list A IHl: list_exists P l -> {x : A & (InList x l * P x)%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 -> {x : A & (InList x l * P x)%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 -> {x : A & (InList x l * P x)%type} x: A ex: list_exists P l x': A H: InList x' l Px': P x'
(((x = x') + InList x' l) * P x')%type
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: forallx : A, InList x l -> P x -> 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: forallx : A, InList x l -> P x -> 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: forallx : A, InList x l -> P x -> 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: forallx : A, InList x l -> P x -> list_exists P l x, y: A p: P y
x = y -> P x
A: Type P: A -> Type l: list A IHl: forallx : A, InList x l -> P x -> 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: forallx : A, InList x l -> P x -> 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: forallx : A, InList x l -> P x -> 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: forallx : A, InList x l -> P x -> 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: forallk : nat, P k -> k < n k: nat p: P k
list_exists P (seq n)
n: nat P: nat -> Type H: forallk : nat, P k -> k < n k: nat p: P k
InList k (seq n)
n: nat P: nat -> Type H: forallk : nat, P k -> k < 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: forallk : nat, P k -> k < n k: nat Hk: InList k (seq n) p: P k
{k : nat & P k}
n: nat P: nat -> Type H: forallk : nat, P k -> k < 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) _.