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.
(** * HPropositions *)
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
exact (1 *E equiv_hprop_allpath _).Defined.(** ** Logical equivalence of hprops *)(** Logical equivalence of hprops is not just logically equivalent to equivalence, it is equivalent to it. *)
H: Funext A, B: Type IsHProp0: IsHProp A IsHProp1: IsHProp B
IsEquiv equiv_iff_hprop_uncurried
H: Funext A, B: Type IsHProp0: IsHProp A IsHProp1: IsHProp B
IsEquiv equiv_iff_hprop_uncurried
H: Funext A, B: Type IsHProp0: IsHProp A IsHProp1: IsHProp B i:= @istrunc_equiv: Funext ->
forall (n : trunc_index)
(AB : Type),
IsTrunc n.+1 B -> IsTrunc n.+1 (A <~> B)
IsEquiv equiv_iff_hprop_uncurried
refine (isequiv_adjointify
equiv_iff_hprop_uncurried
(fune => (@equiv_fun _ _ e, @equiv_inv _ _ e _))
_ _);
intro;
byapply path_ishprop.Defined.Definitionequiv_equiv_iff_hprop
`{Funext} (A B : Type) `{IsHProp A} `{IsHProp B}
: (A <-> B) <~> (A <~> B)
:= Build_Equiv _ _ (@equiv_iff_hprop_uncurried A _ B _) _.(** ** Inhabited and uninhabited hprops *)(** If an hprop is inhabited, then it is equivalent to [Unit]. *)
hprop: Type IsHProp0: IsHProp hprop
hprop -> hprop <~> Unit
hprop: Type IsHProp0: IsHProp hprop
hprop -> hprop <~> Unit
hprop: Type IsHProp0: IsHProp hprop p: hprop
hprop <~> Unit
hprop: Type IsHProp0: IsHProp hprop p: hprop
hprop -> Unit
hprop: Type IsHProp0: IsHProp hprop p: hprop
Unit -> hprop
hprop: Type IsHProp0: IsHProp hprop p: hprop
hprop -> Unit
exact (fun_ => tt).
hprop: Type IsHProp0: IsHProp hprop p: hprop
Unit -> hprop
exact (fun_ => p).Defined.(** If an hprop is not inhabited, then it is equivalent to [Empty]. *)
hprop: Type IsHProp0: IsHProp hprop
~ hprop -> hprop <~> Empty
hprop: Type IsHProp0: IsHProp hprop
~ hprop -> hprop <~> Empty
hprop: Type IsHProp0: IsHProp hprop np: ~ hprop
hprop <~> Empty
exact (Build_Equiv _ _ np _).Defined.(** Thus, a decidable hprop is either equivalent to [Unit] or [Empty]. *)
hprop: Type IsHProp0: IsHProp hprop H: Decidable hprop
(hprop <~> Unit) + (hprop <~> Empty)
hprop: Type IsHProp0: IsHProp hprop H: Decidable hprop
(hprop <~> Unit) + (hprop <~> Empty)
hprop: Type IsHProp0: IsHProp hprop H: Decidable hprop x: hprop
exact (inr (if_not_hprop_then_equiv_Empty hprop nx)).Defined.(** ** Stable types and stable hprops *)(** Recall that a type [A] is "stable" if [~~A -> A]. *)(** When [A] is an hprop, so is [Stable A] (by [ishprop_stable_hprop]), so [Stable A * IsHProp A] is an hprop for any [A]. *)
H: Funext A: Type
IsHProp (Stable A * IsHProp A)
H: Funext A: Type
IsHProp (Stable A * IsHProp A)
H: Funext A: Type stable: Stable A ishprop: IsHProp A
IsHProp (Stable A * IsHProp A)
exact _.Defined.(** Under function extensionality, if [A] is a stable type, then [~~A] is the propositional truncation of [A]. Here, for dependency reasons, we don't give the equivalence to [Tr (-1) A], but just show that the recursion principle holds. See Metatheory/ImpredicativeTruncation.v for a generalization to all types, and Modalities/Notnot.v for a description of the universal property of [~~A] when [A] is not assumed to be stable. *)(** Any negation is an hprop, by [istrunc_Empty] and [istrunc_arrow]. In particular, double-negation is an hprop. *)Definitionishprop_not_not `{Funext} {A : Type} : IsHProp (~~A) := _.(** The recursion principle for [~~A] when [A] is stable. *)
A: Type stable: Stable A P: HProp f: A -> P
~~ A -> P
A: Type stable: Stable A P: HProp f: A -> P
~~ A -> P
A: Type stable: Stable A P: HProp f: A -> P nna: ~~ A
P
exact (f (stable nna)).Defined.(** The unit is [not_not_unit : A -> ~~A], and the computation rule only holds propositionally. *)Definitionnot_not_rec_beta {A : Type} `{Stable A} (P : HProp) (f : A -> P) (a : A)
: not_not_rec P f (not_not_unit a) = f a
:= path_ishprop _ _.(** The map [A -> ~~A] is an equivalence if and only if [A] is a stable hprop. This characterizes the local types for the double-negation modality. See Modality/Notnot.v. *)
H: Funext A: Type stable: Stable A ishprop: IsHProp A
IsEquiv not_not_unit
H: Funext A: Type stable: Stable A ishprop: IsHProp A
~~ A -> A
exact stable.Defined.(** We can upgrade the previous "iff" result to an equivalence. *)Definitionequiv_isequiv_not_not_unit_stable_hprop `{Funext} (P : Type)
: IsEquiv (@not_not_unit P) <~> (Stable P * IsHProp P)
:= equiv_iff_hprop_uncurried (isequiv_not_not_unit_iff_stable_hprop P).(** ** A generalization of [ishprop_decpaths] *)(** Under [Funext], [ishprop_decpaths] shows that [DecidablePaths A] is an hprop. More generally, it's also an hprop with the first argument fixed. *)
H: Funext A: Type x: A
IsHProp (forally : A, Decidable (x = y))
H: Funext A: Type x: A
IsHProp (forally : A, Decidable (x = y))
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y)
d = d'
(* Define [C] to be the component of [A] containing [x]. Since [x = y] is decidable, it is stable, so we can use [~~(x = y)] as an elementary form of propositional truncation. It also works to use [merely] here, but that brings in further dependencies and requires HITs. *)
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type
d = d'
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type
Contr C
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type cC: Contr C
d = d'
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type
Contr C
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type
forally : C, (x; not_not_unit 1) = y
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type y: A p: ~~ (x = y)
(x; not_not_unit 1) = (y; p)
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type y: A p: ~~ (x = y)
x = y
(* [d y] either solves the goal or contradicts [p]. *)bydestruct (d y).
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type cC: Contr C
d = d'
H: Funext A: Type x: A d, d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A
d y = d' y
H: Funext A: Type x: A d': forally : A, Decidable (x = y) C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d: Decidable (x = y)
d = d' y
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d, d': Decidable (x = y)
d = d'
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d, d': x = y
inl d = inl d'
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d: x = y nd': x <> y
inl d = inr nd'
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A nd: x <> y d': x = y
inr nd = inl d'
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A nd, nd': x <> y
inr nd = inr nd'
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d, d': x = y
inl d = inl d'
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d, d': x = y
d = d'
(* [x] and [y] are "in" the component [C]: *)
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d, d': x = y xC:= (x; not_not_unit 1) : C: C
d = d'
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d, d': x = y xC:= (x; not_not_unit 1) : C: C yC:= (y; not_not_unit d) : C: C
d = d'
(* [d] and [d'] can be lifted to equalities of type [xC = yC] using [path_sigma_hprop], and so up to the computation rule for [pr1_path] (denoted "..1"), our goal is in the image of "..1". *)
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d, d': x = y xC:= (x; not_not_unit 1) : C: C yC:= (y; not_not_unit d) : C: C
(* But since [C] is an hset, the paths in [C] are equal. *)apply ap, path_ishprop.(* The remaining cases are the same as in [ishprop_decpaths], but the last bullet is shorter since typeclass search tells us that [x <> y] is an hprop. *)
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A d: x = y nd': x <> y
inl d = inr nd'
elim (nd' d).
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A nd: x <> y d': x = y
inr nd = inl d'
elim (nd d').
H: Funext A: Type x: A C:= {y : A & ~~ (x = y)}: Type cC: Contr C y: A nd, nd': x <> y