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 Basics.Equivalences Types.Empty Types.Unit Types.Prod.Require Import Modalities.ReflectiveSubuniverse Truncations.Core.Require Import Spaces.List.Core.(** * Path spaces of lists *)(** This proof was adapted from a proof given in Agda/cubical by Evan Cavallo. *)SectionPathList.Context {A : Type}.(** We'll show that this type is equivalent to the path space [l = l'] in [list A]. *)FixpointListEq (ll' : list A) : Type :=
match l, l' with
| nil, nil => Unit
| cons x xs, cons x' xs' => (x = x') * ListEq xs xs'
| _, _ => Empty
end.
A: Type
Reflexive ListEq
A: Type
Reflexive ListEq
A: Type l: list A
ListEq l l
A: Type
ListEq nil nil
A: Type a: A l: list A IHl: ListEq l l
ListEq (a :: l) (a :: l)
A: Type
ListEq nil nil
exact tt.
A: Type a: A l: list A IHl: ListEq l l
ListEq (a :: l) (a :: l)
exact (idpath, IHl).Defined.
A: Type l1, l2: list A p: l1 = l2
ListEq l1 l2
A: Type l1, l2: list A p: l1 = l2
ListEq l1 l2
bydestruct p.Defined.
A: Type l1, l2: list A q: ListEq l1 l2
l1 = l2
A: Type l1, l2: list A q: ListEq l1 l2
l1 = l2
A: Type l2: list A q: ListEq nil l2
nil = l2
A: Type a: A l1, l2: list A q: ListEq (a :: l1) l2 IHl1: foralll2 : list A, ListEq l1 l2 -> l1 = l2
(a :: l1)%list = l2
A: Type a: A l1, l2: list A q: ListEq (a :: l1) l2 IHl1: foralll2 : list A, ListEq l1 l2 -> l1 = l2
(a :: l1)%list = l2
A: Type a: A l1: list A q: ListEq (a :: l1) nil IHl1: foralll2 : list A, ListEq l1 l2 -> l1 = l2
(a :: l1)%list = nil
A: Type a: A l1: list A a0: A l2: list A q: ListEq (a :: l1) (a0 :: l2) IHl1: foralll2 : list A, ListEq l1 l2 -> l1 = l2
(a :: l1)%list = (a0 :: l2)%list
A: Type a: A l1: list A a0: A l2: list A q: ListEq (a :: l1) (a0 :: l2) IHl1: foralll2 : list A, ListEq l1 l2 -> l1 = l2
(a :: l1)%list = (a0 :: l2)%list
A: Type a: A l1: list A a0: A l2: list A p: a = a0 q: ListEq l1 l2 IHl1: foralll2 : list A, ListEq l1 l2 -> l1 = l2
(a :: l1)%list = (a0 :: l2)%list
exact (ap011 (cons (A:=_)) p (IHl1 _ q)).Defined.
A: Type l: list A
decode (reflexivity l) = 1
A: Type l: list A
decode (reflexivity l) = 1
A: Type
decode (reflexivity nil) = 1
A: Type a: A l: list A IHl: decode (reflexivity l) = 1
decode (reflexivity (a :: l)%list) = 1
A: Type a: A l: list A IHl: decode (reflexivity l) = 1
decode (reflexivity (a :: l)%list) = 1
exact (ap02 (cons a) IHl).Defined.
A: Type l1, l2: list A p: l1 = l2
decode (encode p) = p
A: Type l1, l2: list A p: l1 = l2
decode (encode p) = p
A: Type l1: list A
decode (encode 1) = 1
exact decode_refl.Defined.(** By case analysis on both lists, it's easy to show that [ListEq] is [n.+1]-truncated if [A] is [n.+2]-truncated. *)
A: Type n: trunc_index l1, l2: list A H: IsTrunc n.+2 A
IsTrunc n.+1 (ListEq l1 l2)
A: Type n: trunc_index l1, l2: list A H: IsTrunc n.+2 A
IsTrunc n.+1 (ListEq l1 l2)
A: Type n: trunc_index l2: list A H: IsTrunc n.+2 A
IsTrunc n.+1 (ListEq nil l2)
A: Type n: trunc_index a: A l1, l2: list A H: IsTrunc n.+2 A IHl1: foralll2 : list A, IsTrunc n.+1 (ListEq l1 l2)
IsTrunc n.+1 (ListEq (a :: l1) l2)
A: Type n: trunc_index l2: list A H: IsTrunc n.+2 A
IsTrunc n.+1 (ListEq nil l2)
A: Type n: trunc_index H: IsTrunc n.+2 A
IsTrunc n.+1 (ListEq nil nil)
A: Type n: trunc_index a: A l2: list A H: IsTrunc n.+2 A
IsTrunc n.+1 (ListEq nil (a :: l2))
1,2: exact _.
A: Type n: trunc_index a: A l1, l2: list A H: IsTrunc n.+2 A IHl1: foralll2 : list A, IsTrunc n.+1 (ListEq l1 l2)
IsTrunc n.+1 (ListEq (a :: l1) l2)
A: Type n: trunc_index a: A l1: list A H: IsTrunc n.+2 A IHl1: foralll2 : list A, IsTrunc n.+1 (ListEq l1 l2)
IsTrunc n.+1 (ListEq (a :: l1) nil)
A: Type n: trunc_index a: A l1: list A a0: A l2: list A H: IsTrunc n.+2 A IHl1: foralll2 : list A, IsTrunc n.+1 (ListEq l1 l2)
IsTrunc n.+1 (ListEq (a :: l1) (a0 :: l2))
A: Type n: trunc_index a: A l1: list A a0: A l2: list A H: IsTrunc n.+2 A IHl1: foralll2 : list A, IsTrunc n.+1 (ListEq l1 l2)
IsTrunc n.+1 (ListEq (a :: l1) (a0 :: l2))
exact istrunc_prod.Defined.(** The path space of lists is a retract of [ListEq], therefore it is [n.+1]-truncated if [ListEq] is [n.+1]-truncated. By the previous result, this holds when [A] is [n.+2]-truncated. *)
A: Type n: trunc_index H: IsTrunc n.+2 A
IsTrunc n.+2 (list A)
A: Type n: trunc_index H: IsTrunc n.+2 A
IsTrunc n.+2 (list A)
A: Type n: trunc_index H: IsTrunc n.+2 A
forallxy : list A, IsTrunc n.+1 (x = y)
A: Type n: trunc_index H: IsTrunc n.+2 A x, y: list A
IsTrunc n.+1 (x = y)
exact (inO_retract_inO n.+1 _ _ encode decode decode_encode).Defined.(** With a little more work, we can show that [ListEq] is also a retract of the path space. *)
A: Type l1, l2: list A p: ListEq l1 l2
encode (decode p) = p
A: Type l1, l2: list A p: ListEq l1 l2
encode (decode p) = p
A: Type l2: list A p: ListEq nil l2
encode (decode p) = p
A: Type a: A l1, l2: list A p: ListEq (a :: l1) l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
encode (decode p) = p
A: Type a: A l1, l2: list A p: ListEq (a :: l1) l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
encode (decode p) = p
A: Type a: A l1: list A p: ListEq (a :: l1) nil IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
encode (decode p) = p
A: Type a: A l1: list A a0: A l2: list A p: ListEq (a :: l1) (a0 :: l2) IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
encode (decode p) = p
A: Type a: A l1: list A a0: A l2: list A p: ListEq (a :: l1) (a0 :: l2) IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
encode (decode p) = p
A: Type a: A l1: list A a0: A l2: list A p: (a = a0) * ListEq l1 l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
encode (decode p) = p
A: Type a: A l1: list A a0: A l2: list A r: a = a0 p: ListEq l1 l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
encode (decode (r, p)) = (r, p)
A: Type a: A l1: list A a0: A l2: list A r: a = a0 p: ListEq l1 l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
fst (encode (decode (r, p))) = fst (r, p)
A: Type a: A l1: list A a0: A l2: list A r: a = a0 p: ListEq l1 l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
snd (encode (decode (r, p))) = snd (r, p)
A: Type a: A l1: list A a0: A l2: list A r: a = a0 p: ListEq l1 l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
fst (encode (decode (r, p))) = fst (r, p)
A: Type a: A l1: list A a0: A l2: list A r: a = a0 p: ListEq l1 l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
fst (encode (ap011 cons r (decode p))) = r
A: Type a: A l1: list A a0: A r: a = a0 p: ListEq l1 l1 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
fst (encode (ap011 cons r 1)) = r
bydestruct r.
A: Type a: A l1: list A a0: A l2: list A r: a = a0 p: ListEq l1 l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p
snd (encode (decode (r, p))) = snd (r, p)
A: Type a: A l1: list A a0: A l2: list A r: a = a0 p: ListEq l1 l2 IHl1: forall (l2 : list A) (p : ListEq l1 l2),
encode (decode p) = p