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.
(** * Theorems about Sigma-types (dependent sums) *)
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
Require Import Types.Arrow Types.Paths.LocalOpen Scope path_scope.Generalizable VariablesX A B C f g n.(** In homotopy type theory, we think of elements of [Type] as spaces, homotopy types, or weak omega-groupoids. A type family [P : A -> Type] corresponds to a fibration whose base is [A] and whose fiber over [x] is [P x].From such a [P] we can build a total space over the base space [A] so that the fiber over [x : A] is [P x]. This is just Coq's dependent sum construction, written as [sig P] or [{x : A & P x}]. The elements of [{x : A & P x}] are pairs, written [exist P x y] in Coq, where [x : A] and [y : P x]. In [Overture.v], we defined the notation [(x; y)] to mean [exist _ x y].The base and fiber components of a point in the total space are extracted with the two projections [pr1] and [pr2]. *)(** ** Eta conversion *)Definitioneta_sigma `{P : A -> Type} (u : sig P)
: (u.1; u.2) = u
:= 1.Arguments eta_sigma / .Definitioneta2_sigma `{P : forall (a : A) (b : B a), Type}
(u : sig (funa => sig (P a)))
: (u.1; u.2.1; u.2.2) = u
:= 1.Arguments eta2_sigma / .Definitioneta3_sigma `{P : forall (a : A) (b : B a) (c : C a b), Type}
(u : sig (funa => sig (funb => sig (P a b))))
: (u.1; u.2.1; u.2.2.1; u.2.2.2) = u
:= 1.Arguments eta3_sigma / .(** ** Paths *)(** A path in a total space is commonly shown component wise. Because we use this over and over, we write down the proofs by hand to make sure they are what we think they should be. *)(** With this version of the function, we often have to give [u] and [v] explicitly, so we make them explicit arguments. *)Definitionpath_sigma_uncurried {A : Type} (P : A -> Type) (uv : sig P)
(pq : {p : u.1 = v.1 & p # u.2 = v.2})
: u = v
:= match pq.2in (_ = v2) return u = (v.1; v2) with
| 1 => match pq.1as p in (_ = v1) return u = (v1; p # u.2) with
| 1 => 1endend.(** This is the curried one you usually want to use in practice. We define it in terms of the uncurried one, since it's the uncurried one that is proven below to be an equivalence. *)Definitionpath_sigma {A : Type} (P : A -> Type) (uv : sig P)
(p : u.1 = v.1) (q : p # u.2 = v.2)
: u = v
:= path_sigma_uncurried P u v (p;q).(** A contravariant instance of [path_sigma_uncurried] *)Definitionpath_sigma_uncurried_contra {A : Type} (P : A -> Type) (uv : sig P)
(pq : {p : u.1 = v.1 & u.2 = p^ # v.2})
: u = v
:= (path_sigma_uncurried P v u (pq.1^;pq.2^))^.(** A variant of [Forall.dpath_forall] from which uses dependent sums to package things. It cannot go into [Forall] because [Sigma] depends on [Forall]. *)
A: Type P: A -> Type Q: {x : _ & P x} -> Type x, y: A h: x = y f: forallp : P x, Q (x; p) g: forallp : P y, Q (y; p)
(forallp : P x,
transport Q
(path_sigma P (x; p)
(y;
match h in (_ = a) return (P a) with
| 1 => (x; p).2end) h 1) (f p) = g (transport P h p)) <~>
(forallp : P x,
transportD P (fun (x : A) (p0 : P x) => Q (x; p0)) h
p (f p) = g (transport P h p))
A: Type P: A -> Type Q: {x : _ & P x} -> Type x, y: A h: x = y f: forallp : P x, Q (x; p) g: forallp : P y, Q (y; p)
(forallp : P x,
transport Q
(path_sigma P (x; p)
(y;
match h in (_ = a) return (P a) with
| 1 => (x; p).2end) h 1) (f p) = g (transport P h p)) <~>
(forallp : P x,
transportD P (fun (x : A) (p0 : P x) => Q (x; p0)) h
p (f p) = g (transport P h p))
A: Type P: A -> Type Q: {x : _ & P x} -> Type x: A f, g: forallp : P x, Q (x; p)
(forallp : P x,
transport Q (path_sigma P (x; p) (x; (x; p).2) 11)
(f p) = g (transport P 1 p)) <~>
(forallp : P x,
transportD P (fun (x : A) (p0 : P x) => Q (x; p0)) 1
p (f p) = g (transport P 1 p))
exact1%equiv.Defined.(** This version produces only paths between pairs, as opposed to paths between arbitrary inhabitants of dependent sum types. But it has the advantage that the components of those pairs can more often be inferred, so we make them implicit arguments. *)Definitionpath_sigma' {A : Type} (P : A -> Type) {xx' : A} {y : P x} {y' : P x'}
(p : x = x') (q : p # y = y')
: (x;y) = (x';y')
:= path_sigma P (x;y) (x';y') p q.(** Projections of paths from a total space. *)Definitionpr1_path `{P : A -> Type} {u v : sig P} (p : u = v)
: u.1 = v.1
:= ap pr1 p.(* match p with idpath => 1 end. *)Notation"p ..1" := (pr1_path p) : fibration_scope.Definitionpr2_path `{P : A -> Type} {u v : sig P} (p : u = v)
: p..1 # u.2 = v.2
:= (transport_compose P pr1 p u.2)^
@ (@apD {x:A & P x} _ pr2 _ _ p).Notation"p ..2" := (pr2_path p) : fibration_scope.(** Now we show how these things compute. *)
A: Type P: A -> Type u, v: {x : _ & P x} pq: {p : u.1 = v.1 & transport P p u.2 = v.2}
(path_sigma_uncurried P u v pq) ..1 = pq.1
A: Type P: A -> Type u, v: {x : _ & P x} pq: {p : u.1 = v.1 & transport P p u.2 = v.2}
(path_sigma_uncurried P u v pq) ..1 = pq.1
A: Type P: A -> Type u1: A u2: P u1 v1: A v2: P v1 pq: {p : u1 = v1 & transport P p u2 = v2}
(path_sigma_uncurried P (u1; u2) (v1; v2) pq) ..1 =
pq.1
A: Type P: A -> Type u1: A u2: P u1 v1: A v2: P v1 p: u1 = v1 q: transport P p u2 = v2
A: Type P: A -> Type u, v: {x : _ & P x} pq: {p : u.1 = v.1 & transport P p u.2 = v.2} Q: A -> Type
transport (funx : {x : _ & P x} => Q x.1)
(path_sigma_uncurried P u v pq) = transport Q pq.1
A: Type P: A -> Type u, v: {x : _ & P x} pq: {p : u.1 = v.1 & transport P p u.2 = v.2} Q: A -> Type
transport (funx : {x : _ & P x} => Q x.1)
(path_sigma_uncurried P u v pq) = transport Q pq.1
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 p: proj1 = proj0 q: transport P p proj2 = proj3 Q: A -> Type
transport (funx : {x : _ & P x} => Q x.1)
match
q in (_ = v2)
return ((proj1; proj2) = (proj0; v2))
with
| 1 =>
match
p in (_ = v1)
return
((proj1; proj2) = (v1; transport P p proj2))
with
| 1 => 1endend = transport Q p
A: Type P: A -> Type proj1: A proj2: P proj1 Q: A -> Type
transport (funx : {x : _ & P x} => Q x.1) 1 =
transport Q 1
reflexivity.Defined.Definitionpr1_path_sigma `{P : A -> Type} {u v : sig P}
(p : u.1 = v.1) (q : p # u.2 = v.2)
: (path_sigma _ _ _ p q)..1 = p
:= pr1_path_sigma_uncurried (p; q).(* Writing it the other way can help [rewrite]. *)Definitionap_pr1_path_sigma {A:Type} {P : A -> Type} {uv : sig P}
(p : u.1 = v.1) (q : p # u.2 = v.2)
: ap pr1 (path_sigma _ _ _ p q) = p
:= pr1_path_sigma p q.Definitionpr2_path_sigma `{P : A -> Type} {u v : sig P}
(p : u.1 = v.1) (q : p # u.2 = v.2)
: (path_sigma _ _ _ p q)..2
= ap (funs => transport P s u.2) (pr1_path_sigma p q) @ q
:= pr2_path_sigma_uncurried (p; q).Definitioneta_path_sigma `{P : A -> Type} {u v : sig P} (p : u = v)
: path_sigma _ _ _ (p..1) (p..2) = p
:= eta_path_sigma_uncurried p.Definitiontransport_pr1_path_sigma
`{P : A -> Type} {u v : sig P}
(p : u.1 = v.1) (q : p # u.2 = v.2)
Q
: transport (funx => Q x.1) (@path_sigma A P u v p q)
= transport _ p
:= transport_pr1_path_sigma_uncurried (p; q) Q.(** This lets us identify the path space of a sigma-type, up to equivalence. *)
A: Type P: A -> Type u, v: {x : _ & P x}
IsEquiv (path_sigma_uncurried P u v)
A: Type P: A -> Type u, v: {x : _ & P x}
IsEquiv (path_sigma_uncurried P u v)
A: Type P: A -> Type u, v: {x : _ & P x}
(funr : u = v => (r ..1; r ..2))
o path_sigma_uncurried P u v == idmap
A: Type P: A -> Type u, v: {x : _ & P x}
forallx : {p : u.1 = v.1 & transport P p u.2 = v.2},
eta_path_sigma (path_sigma_uncurried P u v x) =
ap (path_sigma_uncurried P u v) (?eissect x)
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 p: (proj1; proj2).1 = (proj0; proj3).1 q: transport P p (proj1; proj2).2 = (proj0; proj3).2
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 p: (proj1; proj2).1 = (proj0; proj3).1 q: transport P p (proj1; proj2).2 = (proj0; proj3).2
eta_path_sigma
(path_sigma_uncurried P
(proj1; proj2) (proj0; proj3)
(p; q)) =
ap
(path_sigma_uncurried P
(proj1; proj2) (proj0; proj3))
?Goal
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 p: proj1 = proj0 q: transport P p proj2 = proj3
(match
q in (_ = v2) return ((proj1; proj2) = (proj0; v2))
with
| 1 =>
match
p in (_ = v1)
return
((proj1; proj2) = (v1; transport P p proj2))
with
| 1 => 1endend ..1;
match
q in (_ = v2) return ((proj1; proj2) = (proj0; v2))
with
| 1 =>
match
p in (_ = v1)
return
((proj1; proj2) = (v1; transport P p proj2))
with
| 1 => 1endend ..2) = (p; q)
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 p: proj1 = proj0 q: transport P p proj2 = proj3
eta_path_sigma
match
q in (_ = v2)
return ((proj1; proj2) = (proj0; v2))
with
| 1 =>
match
p in (_ = v1)
return
((proj1; proj2) = (v1; transport P p proj2))
with
| 1 => 1endend =
ap
(path_sigma_uncurried P
(proj1; proj2) (proj0; proj3))
?Goal
A: Type P: A -> Type proj1: A proj2: P proj1
(1; 1 ..2) = (1; 1)
A: Type P: A -> Type proj1: A proj2: P proj1
1 =
ap
(path_sigma_uncurried P
(proj1; proj2) (proj1; proj2))
?Goal
all: reflexivity.Defined.Definitionequiv_path_sigma `(P : A -> Type) (u v : sig P)
: {p : u.1 = v.1 & p # u.2 = v.2} <~> (u = v)
:= Build_Equiv _ _ (path_sigma_uncurried P u v) _.(* A contravariant version of [isequiv_path_sigma'] *)
A: Type P: A -> Type u, v: {x : _ & P x}
IsEquiv (path_sigma_uncurried_contra P u v)
A: Type P: A -> Type u, v: {x : _ & P x}
IsEquiv (path_sigma_uncurried_contra P u v)
A: Type P: A -> Type u, v: {x : _ & P x}
(funx : u = v =>
path_sigma_uncurried_contra P u v
match
x in (_ = s)
return {p : u.1 = s.1 & u.2 = transport P p^ s.2}
with
| 1 => (1; 1)
end) == idmap
A: Type P: A -> Type u, v: {x : _ & P x}
(funx : {p : u.1 = v.1 & u.2 = transport P p^ v.2} =>
match
path_sigma_uncurried_contra P u v x in (_ = s)
return {p : u.1 = s.1 & u.2 = transport P p^ s.2}
with
| 1 => (1; 1)
end) == idmap
A: Type P: A -> Type u, v: {x : _ & P x}
(funx : u = v =>
path_sigma_uncurried_contra P u v
match
x in (_ = s)
return {p : u.1 = s.1 & u.2 = transport P p^ s.2}
with
| 1 => (1; 1)
end) == idmap
byintro r; induction r; destruct u as [u1 u2]; reflexivity.
A: Type P: A -> Type u, v: {x : _ & P x}
(funx : {p : u.1 = v.1 & u.2 = transport P p^ v.2} =>
match
path_sigma_uncurried_contra P u v x in (_ = s)
return {p : u.1 = s.1 & u.2 = transport P p^ s.2}
with
| 1 => (1; 1)
end) == idmap
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 p: (proj1; proj2).1 = (proj0; proj3).1 q: (proj1; proj2).2 = transport P p^ (proj0; proj3).2
match
path_sigma_uncurried_contra P (proj1; proj2)
(proj0; proj3) (p; q) in (_ = s)
return
{p : (proj1; proj2).1 = s.1 &
(proj1; proj2).2 = transport P p^ s.2}
with
| 1 => (1; 1)
end = (p; q)
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 p: proj1 = proj0 q: proj2 = transport P p^ proj3
match
path_sigma_uncurried_contra P
(proj1; proj2) (proj0; proj3)
(p; q) in (_ = s)
return
{p : proj1 = s.1 & proj2 = transport P p^ s.2}
with
| 1 => (1; 1)
end = (p; q)
A: Type P: A -> Type proj1: A proj2, proj3: P proj1 q: proj2 = proj3
match
path_sigma_uncurried_contra P
(proj1; proj2) (proj1; proj3)
(1; q) in (_ = s)
return
{p : proj1 = s.1 & proj2 = transport P p^ s.2}
with
| 1 => (1; 1)
end = (1; q)
destruct q; reflexivity.Defined.(* A contravariant version of [equiv_path_sigma] *)Definitionequiv_path_sigma_contra {A : Type} `(P : A -> Type) (u v : sig P)
: {p : u.1 = v.1 & u.2 = p^ # v.2} <~> (u = v)
:= Build_Equiv _ _ (path_sigma_uncurried_contra P u v) _.(** This identification respects path concatenation. *)
A: Type P: A -> Type u, v, w: {x : _ & P x} p1: u.1 = v.1 q1: transport P p1 u.2 = v.2 p2: v.1 = w.1 q2: transport P p2 v.2 = w.2
path_sigma P u w (p1 @ p2)
((transport_pp P p1 p2 u.2 @ ap (transport P p2) q1) @
q2) =
path_sigma P u v p1 q1 @ path_sigma P v w p2 q2
A: Type P: A -> Type u, v, w: {x : _ & P x} p1: u.1 = v.1 q1: transport P p1 u.2 = v.2 p2: v.1 = w.1 q2: transport P p2 v.2 = w.2
path_sigma P u w (p1 @ p2)
((transport_pp P p1 p2 u.2 @ ap (transport P p2) q1) @
q2) =
path_sigma P u v p1 q1 @ path_sigma P v w p2 q2
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 proj4: A proj5: P proj4 p1: (proj1; proj2).1 = (proj0; proj3).1 q1: transport P p1 (proj1; proj2).2 =
(proj0; proj3).2 p2: (proj0; proj3).1 = (proj4; proj5).1 q2: transport P p2 (proj0; proj3).2 =
(proj4; proj5).2
path_sigma P (proj1; proj2) (proj4; proj5) (p1 @ p2)
((transport_pp P p1 p2 (proj1; proj2).2 @
ap (transport P p2) q1) @ q2) =
path_sigma P (proj1; proj2) (proj0; proj3) p1 q1 @
path_sigma P (proj0; proj3) (proj4; proj5) p2 q2
A: Type P: A -> Type proj1: A proj2: P proj1 proj0: A proj3: P proj0 proj4: A proj5: P proj4 p1: proj1 = proj0 q1: transport P p1 proj2 = proj3 p2: proj0 = proj4 q2: transport P p2 proj3 = proj5
path_sigma P (proj1; proj2)
(proj4; proj5) (p1 @ p2)
((transport_pp P p1 p2 proj2 @
ap (transport P p2) q1) @ q2) =
path_sigma P (proj1; proj2) (proj0; proj3) p1 q1 @
path_sigma P (proj0; proj3) (proj4; proj5) p2 q2
A: Type P: A -> Type proj1: A proj2: P proj1
path_sigma P (proj1; proj2)
(proj1; transport P 1 (transport P 1 proj2))
(1 @ 1)
((transport_pp P 11 proj2 @ ap (transport P 1) 1) @
1) =
path_sigma P (proj1; proj2)
(proj1; transport P 1 proj2) 11 @
path_sigma P (proj1; transport P 1 proj2)
(proj1; transport P 1 (transport P 1 proj2)) 11
reflexivity.Defined.Definitionpath_sigma_pp_pp' {A : Type} (P : A -> Type)
{u1v1w1 : A} {u2 : P u1} {v2 : P v1} {w2 : P w1}
(p1 : u1 = v1) (q1 : p1 # u2 = v2)
(p2 : v1 = w1) (q2 : p2 # v2 = w2)
: path_sigma' P (p1 @ p2)
(transport_pp P p1 p2 u2 @ ap (transport P p2) q1 @ q2)
= path_sigma' P p1 q1 @ path_sigma' P p2 q2
:= @path_sigma_pp_pp A P (u1;u2) (v1;v2) (w1;w2) p1 q1 p2 q2.
A: Type P: A -> Type u1, v1: A u2: P u1 v2: P v1 p: u1 = v1 q: transport P p u2 = v2
path_sigma' P p q =
path_sigma' P p 1 @ path_sigma' P 1 q
A: Type P: A -> Type u1, v1: A u2: P u1 v2: P v1 p: u1 = v1 q: transport P p u2 = v2
path_sigma' P p q =
path_sigma' P p 1 @ path_sigma' P 1 q
A: Type P: A -> Type u1: A u2: P u1
path_sigma' P 11 =
path_sigma' P 11 @ path_sigma' P 11
reflexivity.Defined.(** [pr1_path] also commutes with the groupoid structure. *)Definitionpr1_path_1 {A : Type} {P : A -> Type} (u : sig P)
: (idpath u) ..1 = idpath (u .1)
:= 1.Definitionpr1_path_pp {A : Type} {P : A -> Type} {uvw : sig P}
(p : u = v) (q : v = w)
: (p @ q) ..1 = (p ..1) @ (q ..1)
:= ap_pp _ _ _.Definitionpr1_path_V {A : Type} {P : A -> Type} {uv : sig P} (p : u = v)
: p^ ..1 = (p ..1)^
:= ap_V _ _.(** Applying [exist] to one argument is the same as [path_sigma] with reflexivity in the first place. *)
A: Type P: A -> Type x: A y1, y2: P x q: y1 = y2
ap (exist P x) q = path_sigma' P 1 q
A: Type P: A -> Type x: A y1, y2: P x q: y1 = y2
ap (exist P x) q = path_sigma' P 1 q
destruct q; reflexivity.Defined.(** Dependent transport is the same as transport along a [path_sigma]. *)
A: Type B: A -> Type C: {x : _ & B x} -> Type x1, x2: A p: x1 = x2 y: B x1 z: C (x1; y)
transportD B (fun (a : A) (b : B a) => C (a; b)) p y z =
transport C (path_sigma' B p 1) z
A: Type B: A -> Type C: {x : _ & B x} -> Type x1, x2: A p: x1 = x2 y: B x1 z: C (x1; y)
transportD B (fun (a : A) (b : B a) => C (a; b)) p y z =
transport C (path_sigma' B p 1) z
A: Type B: A -> Type C: {x : _ & B x} -> Type x1: A y: B x1 z: C (x1; y)
transportD B (fun (a : A) (b : B a) => C (a; b)) 1 y z =
transport C (path_sigma' B 11) z
reflexivity.Defined.(** Doubly dependent transport is the same as transport along a [path_sigma]. *)
A: Type B: A -> Type C: foralla : A, B a -> Type a1, a2: A pA: a1 = a2 b1: B a1 b2: B a2 pB: transport B pA b1 = b2 c1: C a1 b1
transportDD B C pA pB c1 =
transport (funab : {x : _ & B x} => C ab.1 ab.2)
(path_sigma' B pA pB) c1
A: Type B: A -> Type C: foralla : A, B a -> Type a1, a2: A pA: a1 = a2 b1: B a1 b2: B a2 pB: transport B pA b1 = b2 c1: C a1 b1
transportDD B C pA pB c1 =
transport (funab : {x : _ & B x} => C ab.1 ab.2)
(path_sigma' B pA pB) c1
bydestruct pB, pA.Defined.(** Applying a two variable function to a [path_sigma]. *)
A, B: Type P: A -> Type F: foralla : A, P a -> B x, x': A y: P x y': P x' p: x = x' q: transport P p y = y'
ap (sig_rec F) (path_sigma' P p q) =
(ap (F x) (moveL_transport_V P p y y' q) @
(transport_arrow_toconst p (F x) y')^) @
ap10 (apD F p) y'
A, B: Type P: A -> Type F: foralla : A, P a -> B x, x': A y: P x y': P x' p: x = x' q: transport P p y = y'
ap (sig_rec F) (path_sigma' P p q) =
(ap (F x) (moveL_transport_V P p y y' q) @
(transport_arrow_toconst p (F x) y')^) @
ap10 (apD F p) y'
destruct p, q; reflexivity.Defined.(* Remark: this is also equal to: *)(* = ap10 (apD F p^)^ y @ transport_arrow_toconst _ _ _ *)(* @ ap (F x') (transport2 _ (inv_V p) y @ q). *)(** And we can simplify when the first equality is [1]. *)
A, B: Type P: A -> Type F: foralla : A, P a -> B a: A x, y: P a p: x = y
ap (funw : {x : _ & P x} => F w.1 w.2)
(path_sigma' P 1 p) = ap (funz : P a => F a z) p
A, B: Type P: A -> Type F: foralla : A, P a -> B a: A x, y: P a p: x = y
ap (funw : {x : _ & P x} => F w.1 w.2)
(path_sigma' P 1 p) = ap (funz : P a => F a z) p
destruct p; reflexivity.Defined.(** Applying a function constructed with [sig_rec] to a [path_sigma] can be computed. Technically this computation should probably go by way of a 2-variable [ap], and should be done in the dependently typed case. *)
A: Type P: A -> Type Q: Type x1, x2: A p: x1 = x2 y1: P x1 y2: P x2 q: transport P p y1 = y2 d: foralla : A, P a -> Q
ap (sig_rec d) (path_sigma' P p q) =
((((transport_const p (d x1 y1))^ @
(ap (transport (fun_ : A => Q) p o d x1)
(transport_Vp P p y1))^) @
(transport_arrow p (d x1) (transport P p y1))^) @
ap10 (apD d p) (transport P p y1)) @ ap (d x2) q
A: Type P: A -> Type Q: Type x1, x2: A p: x1 = x2 y1: P x1 y2: P x2 q: transport P p y1 = y2 d: foralla : A, P a -> Q
ap (sig_rec d) (path_sigma' P p q) =
((((transport_const p (d x1 y1))^ @
(ap (transport (fun_ : A => Q) p o d x1)
(transport_Vp P p y1))^) @
(transport_arrow p (d x1) (transport P p y1))^) @
ap10 (apD d p) (transport P p y1)) @ ap (d x2) q
A: Type P: A -> Type Q: Type x1: A y1, y2: P x1 q: transport P 1 y1 = y2 d: foralla : A, P a -> Q
ap (sig_rec d) (path_sigma' P 1 q) =
((((transport_const 1 (d x1 y1))^ @
(ap
(funx : P x1 =>
transport (fun_ : A => Q) 1 (d x1 x))
(transport_Vp P 1 y1))^) @
(transport_arrow 1 (d x1) (transport P 1 y1))^) @
ap10 (apD d 1) (transport P 1 y1)) @ ap (d x1) q
A: Type P: A -> Type Q: Type x1: A y1: P x1 d: foralla : A, P a -> Q
ap (sig_rec d) (path_sigma' P 11) =
((((transport_const 1 (d x1 y1))^ @
(ap
(funx : P x1 =>
transport (fun_ : A => Q) 1 (d x1 x))
(transport_Vp P 1 y1))^) @
(transport_arrow 1 (d x1) (transport P 1 y1))^) @
ap10 (apD d 1) (transport P 1 y1)) @ ap (d x1) 1
reflexivity.Defined.(** A path between paths in a total space is commonly shown component wise. *)(** With this version of the function, we often have to give [u] and [v] explicitly, so we make them explicit arguments. *)
A: Type P: A -> Type u, v: {x : _ & P x} p, q: u = v rs: {r : p ..1 = q ..1 &
transport
(funx : u.1 = v.1 => transport P x u.2 = v.2)
r p ..2 = q ..2}
p = q
A: Type P: A -> Type u, v: {x : _ & P x} p, q: u = v rs: {r : p ..1 = q ..1 &
transport
(funx : u.1 = v.1 => transport P x u.2 = v.2)
r p ..2 = q ..2}
p = q
A: Type P: A -> Type proj0: A proj3: P proj0 q: (proj0; proj3) = (proj0; proj3) proj1: 1 ..1 = q ..1 proj2: transport
(funx : (proj0; proj3).1 = (proj0; proj3).1
=>
transport P x (proj0; proj3).2 =
(proj0; proj3).2) proj1
1 ..2 = q ..2
1 = q
A: Type P: A -> Type proj0: A proj3: P proj0 q: (proj0; proj3) = (proj0; proj3) proj1: 1 ..1 = q ..1 proj2: transport
(funx : (proj0; proj3).1 = (proj0; proj3).1
=>
transport P x (proj0; proj3).2 =
(proj0; proj3).2) proj1
1 ..2 = q ..2
A: Type P: A -> Type proj0: A proj3: P proj0 q: (proj0; proj3) = (proj0; proj3)
1 =
path_sigma P (proj0; proj3)
(proj0; proj3) 1 ..1
(transport
(funx : (proj0; proj3).1 = (proj0; proj3).1 =>
transport P x (proj0; proj3).2 =
(proj0; proj3).2) 11 ..2)
reflexivity.Defined.(** This is the curried one you usually want to use in practice. We define it in terms of the uncurried one, since it's the uncurried one that is proven below to be an equivalence. *)Definitionpath_path_sigma {A : Type} (P : A -> Type) (uv : sig P)
(pq : u = v)
(r : p..1 = q..1)
(s : transport (funx => transport P x u.2 = v.2) r p..2 = q..2)
: p = q
:= path_path_sigma_uncurried P u v p q (r; s).(** ** Transport *)(** The concrete description of transport in sigmas (and also pis) is rather trickier than in the other types. In particular, these cannot be described just in terms of transport in simpler types; they require also the dependent transport [transportD]. In particular, this indicates why "transport" alone cannot be fully defined by induction on the structure of types, although Id-elim/[transportD] can be (cf. Observational Type Theory). A more thorough set of lemmas, along the lines of the present ones but dealing with Id-elim rather than just transport, might be nice to have eventually? *)
A: Type B: A -> Type C: foralla : A, B a -> Type x1, x2: A p: x1 = x2 yz: {y : B x1 & C x1 y}
transport (funx : A => {y : B x & C x y}) p yz =
(transport B p yz.1; transportD B C p yz.1 yz.2)
A: Type B: A -> Type C: foralla : A, B a -> Type x1, x2: A p: x1 = x2 yz: {y : B x1 & C x1 y}
transport (funx : A => {y : B x & C x y}) p yz =
(transport B p yz.1; transportD B C p yz.1 yz.2)
A: Type B: A -> Type C: foralla : A, B a -> Type x1: A yz: {y : B x1 & C x1 y}
transport (funx : A => {y : B x & C x y}) 1 yz =
(transport B 1 yz.1; transportD B C 1 yz.1 yz.2)
A: Type B: A -> Type C: foralla : A, B a -> Type x1: A y: B x1 z: C x1 y
transport (funx : A => {y : B x & C x y}) 1 (y; z) =
(transport B 1 (y; z).1;
transportD B C 1 (y; z).1 (y; z).2)
reflexivity.Defined.(** The special case when the second variable doesn't depend on the first is simpler. *)
A, B: Type C: A -> B -> Type x1, x2: A p: x1 = x2 yz: {y : B & C x1 y}
transport (funx : A => {y : B & C x y}) p yz =
(yz.1; transport (funx : A => C x yz.1) p yz.2)
A, B: Type C: A -> B -> Type x1, x2: A p: x1 = x2 yz: {y : B & C x1 y}
transport (funx : A => {y : B & C x y}) p yz =
(yz.1; transport (funx : A => C x yz.1) p yz.2)
A, B: Type C: A -> B -> Type x1: A yz: {y : B & C x1 y}
transport (funx : A => {y : B & C x y}) 1 yz =
(yz.1; transport (funx : A => C x yz.1) 1 yz.2)
A, B: Type C: A -> B -> Type x1: A proj1: B proj2: C x1 proj1
transport (funx : A => {y : B & C x y}) 1
(proj1; proj2) =
((proj1; proj2).1;
transport (funx : A => C x (proj1; proj2).1) 1
(proj1; proj2).2)
reflexivity.Defined.(** Or if the second variable contains a first component that doesn't depend on the first. Need to think about the naming of these. *)
A: Type B, C: A -> Type D: foralla : A, B a -> C a -> Type x1, x2: A p: x1 = x2 yzw: {y : B x1 & {z : C x1 & D x1 y z}}
transport
(funx : A => {y : B x & {z : C x & D x y z}}) p yzw =
(transport B p yzw.1; transport C p (yzw.2).1;
transportD2 B C D p yzw.1 (yzw.2).1 (yzw.2).2)
A: Type B, C: A -> Type D: foralla : A, B a -> C a -> Type x1, x2: A p: x1 = x2 yzw: {y : B x1 & {z : C x1 & D x1 y z}}
transport
(funx : A => {y : B x & {z : C x & D x y z}}) p yzw =
(transport B p yzw.1; transport C p (yzw.2).1;
transportD2 B C D p yzw.1 (yzw.2).1 (yzw.2).2)
A: Type B, C: A -> Type D: foralla : A, B a -> C a -> Type x1: A yzw: {y : B x1 & {z : C x1 & D x1 y z}}
transport
(funx : A => {y : B x & {z : C x & D x y z}}) 1 yzw =
(transport B 1 yzw.1; transport C 1 (yzw.2).1;
transportD2 B C D 1 yzw.1 (yzw.2).1 (yzw.2).2)
reflexivity.Defined.(** ** Functorial action *)Definitionfunctor_sigma `{P : A -> Type} `{Q : B -> Type}
(f : A -> B) (g : foralla, P a -> Q (f a))
: sig P -> sig Q
:= funu => (f u.1 ; g u.1 u.2).
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) u, v: {x : _ & P x} p: u.1 = v.1 q: transport P p u.2 = v.2
ap (functor_sigma f g) (path_sigma P u v p q) =
path_sigma Q (functor_sigma f g u)
(functor_sigma f g v) (ap f p)
(((transport_compose Q f p (g u.1 u.2))^ @
(ap_transport p g u.2)^) @ ap (g v.1) q)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) u, v: {x : _ & P x} p: u.1 = v.1 q: transport P p u.2 = v.2
ap (functor_sigma f g) (path_sigma P u v p q) =
path_sigma Q (functor_sigma f g u)
(functor_sigma f g v) (ap f p)
(((transport_compose Q f p (g u.1 u.2))^ @
(ap_transport p g u.2)^) @ ap (g v.1) q)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) u1: A u2: P u1 v1: A v2: P v1 p: u1 = v1 q: transport P p u2 = v2
ap (functor_sigma f g)
(path_sigma P (u1; u2) (v1; v2) p q) =
path_sigma Q (functor_sigma f g (u1; u2))
(functor_sigma f g (v1; v2)) (ap f p)
(((transport_compose Q f p (g (u1; u2).1 (u1; u2).2))^ @
(ap_transport p g (u1; u2).2)^) @
ap (g (v1; v2).1) q)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) u1: A u2, v2: P u1 q: u2 = v2
ap (functor_sigma f g)
(path_sigma P (u1; u2) (u1; v2) 1 q) =
path_sigma Q (functor_sigma f g (u1; u2))
(functor_sigma f g (u1; v2)) (ap f 1)
(((transport_compose Q f 1 (g (u1; u2).1 (u1; u2).2))^ @
(ap_transport 1 g (u1; u2).2)^) @
ap (g (u1; v2).1) q)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) u1: A u2: P u1
ap (functor_sigma f g)
(path_sigma P (u1; u2) (u1; u2) 11) =
path_sigma Q (functor_sigma f g (u1; u2))
(functor_sigma f g (u1; u2)) (ap f 1)
(((transport_compose Q f 1 (g (u1; u2).1 (u1; u2).2))^ @
(ap_transport 1 g (u1; u2).2)^) @
ap (g (u1; u2).1) 1)
reflexivity.Defined.(** ** Equivalences *)(** The converse to [isequiv_functor_sigma] when [f] is [idmap] is [isequiv_from_functor_sigma] in Types/Equiv.v, which also contains Theorem 4.7.7 *)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
IsEquiv (functor_sigma f g)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
IsEquiv (functor_sigma f g)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
{x : _ & Q x} -> {x : _ & P x}
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
functor_sigma f g o ?g == idmap
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
?g o functor_sigma f g == idmap
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
{x : _ & Q x} -> {x : _ & P x}
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
functor_sigma f g
o functor_sigma f^-1
(fun (b : B) (q : Q b) =>
(g (f^-1 b))^-1 (transport Q (eisretr f b)^ q)) ==
idmap
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) b: B q: Q b
functor_sigma f g
(functor_sigma f^-1
(fun (b : B) (q : Q b) =>
(g (f^-1 b))^-1 (transport Q (eisretr f b)^ q))
(b; q)) = (b; q)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) b: B q: Q b
transport Q (eisretr f b)
(g (f^-1 b)
((g (f^-1 b))^-1 (transport Q (eisretr f b)^ q))) =
q
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) b: B q: Q b
transport Q (eisretr f b)
(transport Q (eisretr f b)^ q) = q
apply transport_pV.
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a)
functor_sigma f^-1
(fun (b : B) (q : Q b) =>
(g (f^-1 b))^-1 (transport Q (eisretr f b)^ q))
o functor_sigma f g == idmap
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) a: A p: P a
functor_sigma f^-1
(fun (b : B) (q : Q b) =>
(g (f^-1 b))^-1 (transport Q (eisretr f b)^ q))
(functor_sigma f g (a; p)) = (a; p)
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) a: A p: P a
transport P (eissect f a)
((g (f^-1 (f a)))^-1
(transport Q (eisretr f (f a))^ (g a p))) = p
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) a: A p: P a
(g a)^-1
(transport (funa' : A => Q (f a')) (eissect f a)
(transport Q (eisretr f (f a))^ (g a p))) = p
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) a: A p: P a
(g a)^-1
(transport Q (ap f (eissect f a))
(transport Q (eisretr f (f a))^ (g a p))) = p
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) a: A p: P a
(g a)^-1
(transport Q (eisretr f (f a))
(transport Q (eisretr f (f a))^ (g a p))) = p
A: Type P: A -> Type B: Type Q: B -> Type f: A -> B H: IsEquiv f g: forallx : A, P x -> Q (f x) H0: foralla : A, IsEquiv (g a) a: A p: P a
(g a)^-1 (g a p) = p
apply eissect.Defined.Definitionequiv_functor_sigma `{P : A -> Type} `{Q : B -> Type}
(f : A -> B) `{IsEquiv A B f}
(g : foralla, P a -> Q (f a))
`{foralla, @IsEquiv (P a) (Q (f a)) (g a)}
: sig P <~> sig Q
:= Build_Equiv _ _ (functor_sigma f g) _.Definitionequiv_functor_sigma' `{P : A -> Type} `{Q : B -> Type}
(f : A <~> B)
(g : foralla, P a <~> Q (f a))
: sig P <~> sig Q
:= equiv_functor_sigma f g.Definitionequiv_functor_sigma_id `{P : A -> Type} `{Q : A -> Type}
(g : foralla, P a <~> Q a)
: sig P <~> sig Q
:= equiv_functor_sigma' 1 g.Definitionequiv_functor_sigma_pb {AB : Type} {Q : B -> Type}
(f : A <~> B)
: sig (Q o f) <~> sig Q
:= equiv_functor_sigma f (funa => 1%equiv).(** Lemma 3.11.9(i): Summing up a contractible family of types does nothing. *)
A: Type P: A -> Type H: foralla : A, Contr (P a)
IsEquiv pr1
A: Type P: A -> Type H: foralla : A, Contr (P a)
IsEquiv pr1
A: Type P: A -> Type H: foralla : A, Contr (P a)
(funx : A => (x; center (P x)).1) == idmap
A: Type P: A -> Type H: foralla : A, Contr (P a)
(funx : {x : _ & P x} => (x.1; center (P x.1))) ==
idmap
A: Type P: A -> Type H: foralla : A, Contr (P a)
(funx : A => (x; center (P x)).1) == idmap
intros a; reflexivity.
A: Type P: A -> Type H: foralla : A, Contr (P a)
(funx : {x : _ & P x} => (x.1; center (P x.1))) ==
idmap
A: Type P: A -> Type H: foralla : A, Contr (P a) a: A p: P a
((a; p).1; center (P (a; p).1)) = (a; p)
exact (path_sigma' P 1 (contr _)).Defined.Definitionequiv_sigma_contr {A : Type} (P : A -> Type)
`{foralla, Contr (P a)}
: sig P <~> A
:= Build_Equiv _ _ pr1 _.(** Lemma 3.11.9(ii): Dually, summing up over a contractible type does nothing. *)
A: Type P: A -> Type Contr0: Contr A
{x : A & P x} <~> P (center A)
A: Type P: A -> Type Contr0: Contr A
{x : A & P x} <~> P (center A)
A: Type P: A -> Type Contr0: Contr A
(funx : P (center A) =>
transport (funx0 : A => P x0)
(contr (center A; x).1)^
(center A; x).2) == idmap
A: Type P: A -> Type Contr0: Contr A
(funx : {x : A & P x} =>
(center A;
transport (funx0 : A => P x0) (contr x.1)^ x.2)) ==
idmap
A: Type P: A -> Type Contr0: Contr A
(funx : P (center A) =>
transport (funx0 : A => P x0)
(contr (center A; x).1)^
(center A; x).2) == idmap
A: Type P: A -> Type Contr0: Contr A p: P (center A)
transport (funx : A => P x) (contr (center A))^ p = p
exact (ap (funq => q # p) (path_contr _ 1)).
A: Type P: A -> Type Contr0: Contr A
(funx : {x : A & P x} =>
(center A;
transport (funx0 : A => P x0) (contr x.1)^ x.2)) ==
idmap
A: Type P: A -> Type Contr0: Contr A a: A p: P a
(center A;
transport (funx : A => P x)
(contr (a; p).1)^ (a; p).2) =
(a; p)
A: Type P: A -> Type Contr0: Contr A a: A p: P a
transport (funx : A => P x)
(contr a)
(transport (funx : A => P x)
(contr (a; p).1)^ (a; p).2) = p
apply transport_pV.Defined.(** ** Associativity *)(** All of the following lemmas are proven easily with the [make_equiv] tactic. If you have a more complicated rearrangement of sigma-types to do, it is usually possible to do it by putting together these equivalences, but it is often simpler and faster to just use [make_equiv] directly. *)
A: Type P: A -> Type Q: {a : A & P a} -> Type
{a : A & {p : P a & Q (a; p)}} <~> {x : _ & Q x}
A: Type P: A -> Type Q: {a : A & P a} -> Type
{a : A & {p : P a & Q (a; p)}} <~> {x : _ & Q x}
make_equiv.Defined.
A: Type P: A -> Type Q: foralla : A, P a -> Type
{a : A & {p : P a & Q a p}} <~>
{ap : {x : _ & P x} & Q ap.1 ap.2}
A: Type P: A -> Type Q: foralla : A, P a -> Type
{a : A & {p : P a & Q a p}} <~>
{ap : {x : _ & P x} & Q ap.1 ap.2}
make_equiv.Defined.
A, B: Type Q: A * B -> Type
{a : A & {b : B & Q (a, b)}} <~> {x : _ & Q x}
A, B: Type Q: A * B -> Type
{a : A & {b : B & Q (a, b)}} <~> {x : _ & Q x}
make_equiv.Defined.
A, B: Type Q: A -> B -> Type
{a : A & {b : B & Q a b}} <~>
{ab : A * B & Q (fst ab) (snd ab)}
A, B: Type Q: A -> B -> Type
{a : A & {b : B & Q a b}} <~>
{ab : A * B & Q (fst ab) (snd ab)}
make_equiv.Defined.
A, B: Type
{_ : A & B} <~> A * B
A, B: Type
{_ : A & B} <~> A * B
make_equiv.Defined.Definitionequiv_sigma_prod1 (ABC : Type)
: {a : A & {b : B & C}} <~> A * B * C
:= ltac:(make_equiv).Definitionequiv_sigma_prod_prod {XY : Type} (P : X -> Type) (Q : Y -> Type)
: {z : X * Y & (P (fst z)) * (Q (snd z))} <~> (sig P) * (sig Q)
:= ltac:(make_equiv).(** ** Symmetry *)
A, B: Type P: A -> B -> Type
{a : A & {b : B & P a b}} <~>
{b : B & {a : A & P a b}}
A, B: Type P: A -> B -> Type
{a : A & {b : B & P a b}} <~>
{b : B & {a : A & P a b}}
make_equiv.Defined.
A: Type P, Q: A -> Type
{ap : {a : A & P a} & Q ap.1} <~>
{aq : {a : A & Q a} & P aq.1}
A: Type P, Q: A -> Type
{ap : {a : A & P a} & Q ap.1} <~>
{aq : {a : A & Q a} & P aq.1}
make_equiv.Defined.
A, B: Type
{_ : A & B} <~> {_ : B & A}
A, B: Type
{_ : A & B} <~> {_ : B & A}
make_equiv.Defined.(** ** Universal mapping properties *)(** *** The positive universal property. *)Instanceisequiv_sig_ind `{P : A -> Type} (Q : sig P -> Type)
: IsEquiv (sig_ind Q) | 0
:= Build_IsEquiv
_ _
(sig_ind Q)
(funfxy => f (x;y))
(fun_ => 1)
(fun_ => 1)
(fun_ => 1).Definitionequiv_sig_ind `{P : A -> Type} (Q : sig P -> Type)
: (forall (x:A) (y:P x), Q (x;y)) <~> (forallxy, Q xy)
:= Build_Equiv _ _ (sig_ind Q) _.(** And a curried version *)Definitionequiv_sig_ind' `{P : A -> Type} (Q : foralla, P a -> Type)
: (forall (x:A) (y:P x), Q x y) <~> (forallxy, Q xy.1 xy.2)
:= equiv_sig_ind (funxy => Q xy.1 xy.2).(** *** The negative universal property. *)Definitionsig_coind_uncurried
`{A : X -> Type} (P : forallx, A x -> Type)
: { f : forallx, A x & forallx, P x (f x) }
-> (forallx, sig (P x))
:= funfg => funx => (fg.1 x ; fg.2 x).Definitionsig_coind
`{A : X -> Type} (P : forallx, A x -> Type)
(f : forallx, A x) (g : forallx, P x (f x))
: (forallx, sig (P x))
:= sig_coind_uncurried P (f;g).Instanceisequiv_sig_coind
`{A : X -> Type} {P : forallx, A x -> Type}
: IsEquiv (sig_coind_uncurried P) | 0
:= Build_IsEquiv
_ _
(sig_coind_uncurried P)
(funh => exist (funf => forallx, P x (f x))
(funx => (h x).1)
(funx => (h x).2))
(fun_ => 1)
(fun_ => 1)
(fun_ => 1).Definitionequiv_sig_coind
`(A : X -> Type) (P : forallx, A x -> Type)
: { f : forallx, A x & forallx, P x (f x) }
<~> (forallx, sig (P x))
:= Build_Equiv _ _ (sig_coind_uncurried P) _.(** ** Sigmas preserve truncation *)
A: Type P: A -> Type n: trunc_index IsTrunc0: IsTrunc n A H: foralla : A, IsTrunc n (P a)
IsTrunc n {x : _ & P x}
A: Type P: A -> Type n: trunc_index IsTrunc0: IsTrunc n A H: foralla : A, IsTrunc n (P a)
IsTrunc n {x : _ & P x}
n: trunc_index
forall (A : Type) (P : A -> Type),
IsTrunc n A ->
(foralla : A, IsTrunc n (P a)) ->
IsTrunc n {x : _ & P x}
A: Type P: A -> Type ac: Contr A Pc: foralla : A, Contr (P a)
Contr {x : _ & P x}
n: trunc_index IH: forall (A : Type) (P : A -> Type),
IsTrunc n A ->
(foralla : A, IsTrunc n (P a)) ->
IsTrunc n {x : _ & P x} A: Type P: A -> Type ac: IsTrunc n.+1 A Pc: foralla : A, IsTrunc n.+1 (P a)
IsTrunc n.+1 {x : _ & P x}
A: Type P: A -> Type ac: Contr A Pc: foralla : A, Contr (P a)
Contr {x : _ & P x}
A: Type P: A -> Type ac: Contr A Pc: foralla : A, Contr (P a)
forally : {x : _ & P x},
(center A; center (P (center A))) = y
A: Type P: A -> Type ac: Contr A Pc: foralla : A, Contr (P a) a: A proj2: P a
(center A; center (P (center A))) = (a; proj2)
exact (path_sigma' P (contr a) (path_contr _ _)).
n: trunc_index IH: forall (A : Type) (P : A -> Type),
IsTrunc n A ->
(foralla : A, IsTrunc n (P a)) ->
IsTrunc n {x : _ & P x} A: Type P: A -> Type ac: IsTrunc n.+1 A Pc: foralla : A, IsTrunc n.+1 (P a)
IsTrunc n.+1 {x : _ & P x}
n: trunc_index IH: forall (A : Type) (P : A -> Type),
IsTrunc n A ->
(foralla : A, IsTrunc n (P a)) ->
IsTrunc n {x : _ & P x} A: Type P: A -> Type ac: IsTrunc n.+1 A Pc: foralla : A, IsTrunc n.+1 (P a)
forall (x : {x : _ & P x})
(y : {x : _ & P x}), IsTrunc n (x = y)
n: trunc_index IH: forall (A : Type) (P : A -> Type),
IsTrunc n A ->
(foralla : A, IsTrunc n (P a)) ->
IsTrunc n {x : _ & P x} A: Type P: A -> Type ac: IsTrunc n.+1 A Pc: foralla : A, IsTrunc n.+1 (P a) u, v: {x : _ & P x}
IsTrunc n (u = v)
exact (istrunc_isequiv_istrunc _ (path_sigma_uncurried P u v)).Defined.(** The sigma of an arbitrary family of *disjoint* hprops is an hprop. *)
A: Type P: A -> Type H: foralla : A, IsHProp (P a)
(forallxy : A, P x -> P y -> x = y) ->
IsHProp {x : A & P x}
A: Type P: A -> Type H: foralla : A, IsHProp (P a)
(forallxy : A, P x -> P y -> x = y) ->
IsHProp {x : A & P x}
A: Type P: A -> Type H: foralla : A, IsHProp (P a) dj: forallxy : A, P x -> P y -> x = y x: A px: P x y: A py: P y
(x; px) = (y; py)
A: Type P: A -> Type H: foralla : A, IsHProp (P a) dj: forallxy : A, P x -> P y -> x = y x: A px: P x y: A py: P y
transport P (dj x y px py) px = py
apply path_ishprop.Defined.(** ** Subtypes (sigma types whose second components are hprops) *)(** To prove equality in a subtype, we only need equality of the first component. *)Definitionpath_sigma_hprop {A : Type} {P : A -> Type}
`{forallx, IsHProp (P x)}
(u v : sig P)
: u.1 = v.1 -> u = v
:= path_sigma_uncurried P u v o pr1^-1.Instanceisequiv_path_sigma_hprop {AP} `{forallx : A, IsHProp (P x)} {u v : sig P}
: IsEquiv (@path_sigma_hprop A P _ u v) | 100
:= isequiv_compose _ _.#[export]
Hint Immediate isequiv_path_sigma_hprop : typeclass_instances.Definitionequiv_path_sigma_hprop {A : Type} {P : A -> Type}
{HP : foralla, IsHProp (P a)} (uv : sig P)
: (u.1 = v.1) <~> (u = v)
:= Build_Equiv _ _ (path_sigma_hprop _ _) _.Definitionisequiv_pr1_path_hprop {A} {P : A -> Type}
`{foralla, IsHProp (P a)} (x y : sig P)
: IsEquiv (@pr1_path A P x y)
:= _ : IsEquiv (path_sigma_hprop x y)^-1.#[export]
Hint Immediate isequiv_pr1_path_hprop : typeclass_instances.(** We define this for ease of [SearchAbout IsEquiv ap pr1] *)Definitionisequiv_ap_pr1_hprop {A} {P : A -> Type}
`{foralla, IsHProp (P a)} (x y : sig P)
: IsEquiv (@ap _ _ (@pr1 A P) x y)
:= _.(** [path_sigma_hprop] is functorial *)
A: Type P: A -> Type H: forallx : A, IsHProp (P x) u: {x : _ & P x}
path_sigma_hprop u u 1 = 1
A: Type P: A -> Type H: forallx : A, IsHProp (P x) u: {x : _ & P x}
path_sigma_hprop u u 1 = 1
A: Type P: A -> Type H: forallx : A, IsHProp (P x) u: {x : _ & P x}
path_sigma_uncurried P u u (pr1^-11) = 1
A: Type P: A -> Type H: forallx : A, IsHProp (P x) u: {x : _ & P x}
match
center (u.2 = u.2) in (_ = v2)
return (u = (u.1; v2))
with
| 1 => 1end = 1
(** Ugh *)exact (ap (funp => match p in (_ = v2) return (u = (u.1; v2)) with1 => 1end)
(contr (idpath u.2))).Defined.
A: Type P: A -> Type H: forallx : A, IsHProp (P x) a, b: A p: a = b x: P a y: P b
exact (concat_1p _)^.Qed.(** The inverse of [path_sigma_hprop] has its own name, so we give special names to the section and retraction homotopies to help [rewrite] out. *)Definitionpath_sigma_hprop_ap_pr1 {A : Type} {P : A -> Type}
`{forallx, IsHProp (P x)} (u v : sig P) (p : u = v)
: path_sigma_hprop u v (ap pr1 p) = p
:= eisretr (path_sigma_hprop u v) p.Definitionpath_sigma_hprop_pr1_path {A : Type} {P : A -> Type}
`{forallx, IsHProp (P x)} (u v : sig P) (p : u = v)
: path_sigma_hprop u v p..1 = p
:= eisretr (path_sigma_hprop u v) p.Definitionap_pr1_path_sigma_hprop {A : Type} {P : A -> Type}
`{forallx, IsHProp (P x)} (u v : sig P) (p : u.1 = v.1)
: ap pr1 (path_sigma_hprop u v p) = p
:= eissect (path_sigma_hprop u v) p.Definitionpr1_path_path_sigma_hprop {A : Type} {P : A -> Type}
`{forallx, IsHProp (P x)} (u v : sig P) (p : u.1 = v.1)
: (path_sigma_hprop u v p)..1 = p
:= eissect (path_sigma_hprop u v) p.(** ** Fibers of [functor_sigma] *)
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
hfiber (functor_sigma f g) (b; v) <~>
{w : hfiber f b &
hfiber (g w.1) (transport Q (w.2)^ v)}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
hfiber (functor_sigma f g) (b; v) <~>
{w : hfiber f b &
hfiber (g w.1) (transport Q (w.2)^ v)}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
{x : {x : _ & P x} & (f x.1; g x.1 x.2) = (b; v)} <~>
{w : {x : A & f x = b} &
{x : P w.1 & g w.1 x = transport Q (w.2)^ v}}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
{x : _ & ?Goal0 x} <~>
{w : {x : A & f x = b} &
{x : P w.1 & g w.1 x = transport Q (w.2)^ v}}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
foralla : {x : _ & P x},
(f a.1; g a.1 a.2) = (b; v) <~> ?Goal0 a
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
{a : {x : _ & P x} &
{p : (f a.1; g a.1 a.2).1 = (b; v).1 &
transport Q p (f a.1; g a.1 a.2).2 = (b; v).2}} <~>
{w : {x : A & f x = b} &
{x : P w.1 & g w.1 x = transport Q (w.2)^ v}}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
{a : {x : _ & P x} &
{p : (f a.1; g a.1 a.2).1 = (b; v).1 &
transport Q p (f a.1; g a.1 a.2).2 = (b; v).2}} <~>
{w : {x : A & f x = b} &
{x : P w.1 & transport Q w.2 (g w.1 x) = v}}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
{w : {x : A & f x = b} &
{x : P w.1 & transport Q w.2 (g w.1 x) = v}} <~>
{w : {x : A & f x = b} &
{x : P w.1 & g w.1 x = transport Q (w.2)^ v}}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b
{w : {x : A & f x = b} &
{x : P w.1 & transport Q w.2 (g w.1 x) = v}} <~>
{w : {x : A & f x = b} &
{x : P w.1 & g w.1 x = transport Q (w.2)^ v}}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b a: A p: f a = b
{x : P a & transport Q p (g a x) = v} <~>
{x : P a & g a x = transport Q p^ v}
A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) b: B v: Q b a: A p: f a = b u: P a
transport Q p (g a u) = v <~> g a u = transport Q p^ v
apply equiv_moveL_transport_V.Defined.
n: trunc_index A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) Hf: IsTruncMap n f Hg: foralla : A, IsTruncMap n (g a)
IsTruncMap n (functor_sigma f g)
n: trunc_index A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) Hf: IsTruncMap n f Hg: foralla : A, IsTruncMap n (g a)
IsTruncMap n (functor_sigma f g)
n: trunc_index A, B: Type P: A -> Type Q: B -> Type f: A -> B g: foralla : A, P a -> Q (f a) Hf: IsTruncMap n f Hg: foralla : A, IsTruncMap n (g a) a: B b: Q a