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]
LocalOpen Scope trunc_scope.LocalOpen Scope path_scope.(** * Decidability *)(** ** Definitions *)(* NB: This has to come after our definition of [not] (which is in [Overture]), so that it refers to our [not] rather than the one in [Coq.Logic]. *)ClassDecidable (A : Type) :=
dec : A + (~ A).Arguments dec A {_}.(** The [decide_type] and [decide] tactic allow to automatically provedecidable claims using previously written decision procedures thatcompute. *)Ltacdecide_type A :=
letK := (evalhnfin (dec A)) inmatch K with
| inl ?Z => exact Z
| inr ?Z => exact Z
end.Ltacdecide :=
multimatch goal with
| [|- ?A] => decide_type A
| [|- ~ ?A] => decide_type A
end.
A: Type a: A P: Decidable A -> Type p: forallx : A, P (inl x)
forallp : Decidable A, P p
A: Type a: A P: Decidable A -> Type p: forallx : A, P (inl x)
forallp : Decidable A, P p
A: Type a: A P: Decidable A -> Type p: forallx : A, P (inl x) x: A
P (inl x)
A: Type a: A P: Decidable A -> Type p: forallx : A, P (inl x) n: ~ A
P (inr n)
A: Type a: A P: Decidable A -> Type p: forallx : A, P (inl x) x: A
P (inl x)
apply p.
A: Type a: A P: Decidable A -> Type p: forallx : A, P (inl x) n: ~ A
P (inr n)
contradiction n.Defined.(** Replace a term [p] of the form [Decidable A] with [inl x] if we have a term [a : A] showing that [A] is true. *)Ltacdecidable_true p a :=
generalize p;
rapply (decidable_true a);
tryintro.
A: Type n: ~ A P: Decidable A -> Type p: foralln' : ~ A, P (inr n')
forallp : Decidable A, P p
A: Type n: ~ A P: Decidable A -> Type p: foralln' : ~ A, P (inr n')
forallp : Decidable A, P p
A: Type n: ~ A P: Decidable A -> Type p: foralln' : ~ A, P (inr n') x: A
P (inl x)
A: Type n: ~ A P: Decidable A -> Type p: foralln' : ~ A, P (inr n') n': ~ A
P (inr n')
A: Type n: ~ A P: Decidable A -> Type p: foralln' : ~ A, P (inr n') x: A
P (inl x)
contradiction n.
A: Type n: ~ A P: Decidable A -> Type p: foralln' : ~ A, P (inr n') n': ~ A
P (inr n')
apply p.Defined.(** Replace a term [p] of the form [Decidable A] with [inr na] if we have a term [n : not A] showing that [A] is false. *)Ltacdecidable_false p n :=
generalize p;
rapply (decidable_false n);
tryintro.ClassDecidablePaths (A : Type) :=
dec_paths :: forall (xy : A), Decidable (x = y).ClassStableP := stable : ~~P -> P.(** We always have a map in the other direction. *)Definitionnot_not_unit {P : Type} : P -> ~~P
:= funxnp => np x.Instanceishprop_stable_hprop `{Funext} P `{IsHProp P} : IsHProp (Stable P)
:= istrunc_forall.
P: Type H: Decidable P
Stable P
P: Type H: Decidable P
Stable P
P: Type H: Decidable P dn: ~~ P
P
(* [dec P] either solves the goal or contradicts [dn]. *)bydestruct (dec P).Defined.
P: Type
Stable (~ P)
P: Type
Stable (~ P)
P: Type nnnp: ~~ ~ P p: P
Empty
exact (nnnp (not_not_unit p)).Defined.
P: Type H: Stable P
~~ P <-> P
P: Type H: Stable P
~~ P <-> P
P: Type H: Stable P
~~ P -> P
P: Type H: Stable P
P -> ~~ P
P: Type H: Stable P
~~ P -> P
exact stable.
P: Type H: Stable P
P -> ~~ P
exact not_not_unit.Defined.
A, B: Type f: A <-> B
Stable A -> Stable B
A, B: Type f: A <-> B
Stable A -> Stable B
A, B: Type f: A <-> B stableA: Stable A nnb: ~~ B
B
A, B: Type f: A -> B finv: B -> A stableA: Stable A nnb: ~~ B
B
exact (f (stableA (funna => nnb (funb => na (finv b))))).Defined.Definitionstable_equiv' {AB} (f : A <~> B)
: Stable A -> Stable B
:= stable_iff f.Definitionstable_equiv {AB} (f : A -> B) `{!IsEquiv f}
: Stable A -> Stable B
:= stable_equiv' (Build_Equiv _ _ f _).(** Because [vm_compute] evaluates terms in [PROP] eagerly and does not remove dead code we need the decide_rel hack. Suppose we have [(x = y) =def (f x = f y)], now: [bool_decide (x = y) -> bool_decide (f x = f y) -> ...] As we see, the dead code [f x] and [f y] is actually evaluated, which is of course an utter waste. Therefore we introduce [decide_rel] and [bool_decide_rel]. [bool_decide_rel (=) x y -> bool_decide_rel (fun a b => f a = f b) x y -> ...] Now the definition of equality remains under a lambda and our problem does not occur anymore!*)Definitiondecide_rel {AB} (R : A -> B -> Type)
{dec : forallxy, Decidable (R x y)} (x : A) (y : B)
: Decidable (R x y)
:= dec x y.(** ** Decidable hprops *)(** Contractible types are decidable. *)Instancedecidable_contrX `{Contr X} : Decidable X
:= inl (center X).(** Thus, hprops have decidable equality. *)Instancedecidablepaths_hpropX `{IsHProp X} : DecidablePaths X
:= funxy => dec (x = y).(** Empty types are trivial. *)Instancedecidable_empty : Decidable Empty
:= inr idmap.(** ** Transfer along equivalences *)
A, B: Type f: A <-> B
Decidable A -> Decidable B
A, B: Type f: A <-> B
Decidable A -> Decidable B
A, B: Type f: A <-> B a: A
Decidable B
A, B: Type f: A <-> B na: ~ A
Decidable B
A, B: Type f: A <-> B a: A
Decidable B
exact (inl (fst f a)).
A, B: Type f: A <-> B na: ~ A
Decidable B
exact (inr (funb => na (snd f b))).Defined.Definitiondecidable_equiv' (A : Type) {B : Type} (f : A <~> B)
: Decidable A -> Decidable B
:= decidable_iff f.Definitiondecidable_equiv (A : Type) {B : Type} (f : A -> B) `{!IsEquiv f}
: Decidable A -> Decidable B
:= decidable_equiv' _ (Build_Equiv _ _ f _).
A, B: Type f: A -> B H: IsEquiv f
DecidablePaths A -> DecidablePaths B
A, B: Type f: A -> B H: IsEquiv f
DecidablePaths A -> DecidablePaths B
A, B: Type f: A -> B H: IsEquiv f d: DecidablePaths A x, y: B
Decidable (x = y)
A, B: Type f: A -> B H: IsEquiv f d: DecidablePaths A x, y: B e: f^-1 x = f^-1 y
Decidable (x = y)
A, B: Type f: A -> B H: IsEquiv f d: DecidablePaths A x, y: B ne: f^-1 x <> f^-1 y
Decidable (x = y)
A, B: Type f: A -> B H: IsEquiv f d: DecidablePaths A x, y: B e: f^-1 x = f^-1 y
Decidable (x = y)
A, B: Type f: A -> B H: IsEquiv f d: DecidablePaths A x, y: B e: f^-1 x = f^-1 y
x = y
exact ((eisretr f x)^ @ ap f e @ eisretr f y).
A, B: Type f: A -> B H: IsEquiv f d: DecidablePaths A x, y: B ne: f^-1 x <> f^-1 y
Decidable (x = y)
A, B: Type f: A -> B H: IsEquiv f d: DecidablePaths A x, y: B ne: f^-1 x <> f^-1 y p: x = y
Empty
apply ne, ap, p.Defined.Definitiondecidablepaths_equiv' (A : Type) {B : Type} (f : A <~> B)
: DecidablePaths A -> DecidablePaths B
:= decidablepaths_equiv A f.(** ** Hedberg's theorem: any type with decidable equality is a set. *)(** A weakly constant function is one all of whose values are equal (in a specified way). *)ClassWeaklyConstant {AB} (f : A -> B) :=
wconst : forallxy, f x = f y.(** Any map that factors through an hprop is weakly constant. *)
A, B, P: Type IsHProp0: IsHProp P f: A -> P g: P -> B
WeaklyConstant (g o f)
A, B, P: Type IsHProp0: IsHProp P f: A -> P g: P -> B
WeaklyConstant (g o f)
intros x y; apply (ap g), path_ishprop.Defined.(** A type is collapsible if it admits a weakly constant endomap. *)ClassCollapsible (A : Type) :=
{ collapse : A -> A ;
wconst_collapse :: WeaklyConstant collapse
}.ClassPathCollapsible (A : Type) :=
path_coll :: forall (xy : A), Collapsible (x = y).
A: Type H: Decidable A
Collapsible A
A: Type H: Decidable A
Collapsible A
A: Type H: Decidable A a: A
Collapsible A
A: Type H: Decidable A na: ~ A
Collapsible A
A: Type H: Decidable A a: A
Collapsible A
A: Type H: Decidable A a: A
WeaklyConstant (const a)
intros x y; reflexivity.
A: Type H: Decidable A na: ~ A
Collapsible A
A: Type H: Decidable A na: ~ A
WeaklyConstant idmap
intros x y; destruct (na x).Defined.
A: Type H: DecidablePaths A
PathCollapsible A
A: Type H: DecidablePaths A
PathCollapsible A
intros x y; exact _.Defined.(** We give this a relatively high-numbered priority so that in deducing [IsHProp -> IsHSet] Coq doesn't detour via [DecidablePaths]. *)
A: Type H: PathCollapsible A
IsHSet A
A: Type H: PathCollapsible A
IsHSet A
A: Type H: PathCollapsible A
is_mere_relation A paths
A: Type H: PathCollapsible A x, y: A
IsHProp (x = y)
A: Type H: PathCollapsible A x, y: A
forallp : x = y, p = (collapse 1)^ @ collapse p
A: Type H: PathCollapsible A x, y: A h: forallp : x = y, p = (collapse 1)^ @ collapse p
IsHProp (x = y)
A: Type H: PathCollapsible A x, y: A
forallp : x = y, p = (collapse 1)^ @ collapse p
intros []; symmetry; byapply concat_Vp.
A: Type H: PathCollapsible A x, y: A h: forallp : x = y, p = (collapse 1)^ @ collapse p
IsHProp (x = y)
A: Type H: PathCollapsible A x, y: A h: forallp : x = y, p = (collapse 1)^ @ collapse p p, q: x = y
p = q
A: Type H: PathCollapsible A x, y: A h: forallp : x = y, p = (collapse 1)^ @ collapse p p, q: x = y
A: Type H: PathCollapsible A x, y: A h: forallp : x = y, p = (collapse 1)^ @ collapse p p, q: x = y
collapse p = collapse q
apply wconst.Defined.
A: Type IsHProp0: IsHProp A
Collapsible A
A: Type IsHProp0: IsHProp A
Collapsible A
A: Type IsHProp0: IsHProp A
WeaklyConstant idmap
intros x y; apply path_ishprop.Defined.
A: Type IsHSet0: IsHSet A
PathCollapsible A
A: Type IsHSet0: IsHSet A
PathCollapsible A
intros x y; apply collapsible_hprop; exact _.Defined.(** Hedberg's Theorem *)
A: Type H: DecidablePaths A
IsHSet A
A: Type H: DecidablePaths A
IsHSet A
exact _.Defined.(** We can use Hedberg's Theorem to simplify a goal of the form [forall (d : Decidable (x = x :> A)), P d] when [A] has decidable paths. *)
A: Type H: DecidablePaths A x: A P: Decidable (x = x) -> Type Px: P (inl 1)
foralld : Decidable (x = x), P d
A: Type H: DecidablePaths A x: A P: Decidable (x = x) -> Type Px: P (inl 1)
foralld : Decidable (x = x), P d
A: Type H: DecidablePaths A x: A P: Decidable (x = x) -> Type Px: P (inl 1)
forallx0 : x = x, P (inl x0)
A: Type H: DecidablePaths A x: A P: Decidable (x = x) -> Type Px: P (inl 1) p: x = x
P (inl p)
(** We cannot eliminate [p : x = x] with path induction, but we can use Hedberg's theorem to replace this with [idpath]. *)
A: Type H: DecidablePaths A x: A P: Decidable (x = x) -> Type Px: P (inl 1) p: x = x r: 1 = p
P (inl p)
bydestruct r.Defined.(** ** Truncation *)(** Having decidable equality (which implies being an hset, by Hedberg's theorem above) is itself an hprop. *)
H: Funext A: Type
IsHProp (DecidablePaths A)
H: Funext A: Type
IsHProp (DecidablePaths A)
H: Funext A: Type d: DecidablePaths A
Contr (DecidablePaths A)
H: Funext A: Type d: DecidablePaths A X: IsHSet A
Contr (DecidablePaths A)
H: Funext A: Type d: DecidablePaths A X: IsHSet A
forally : DecidablePaths A, d = y
H: Funext A: Type d: DecidablePaths A X: IsHSet A d': DecidablePaths A
d = d'
H: Funext A: Type d: DecidablePaths A X: IsHSet A d': DecidablePaths A x, y: A
d x y = d' x y
H: Funext A: Type X: IsHSet A d': DecidablePaths A x, y: A d: Decidable (x = y)
d = d' x y
H: Funext A: Type X: IsHSet A x, y: A d, d': Decidable (x = y)
d = d'
H: Funext A: Type X: IsHSet A x, y: A d, d': x = y
inl d = inl d'
H: Funext A: Type X: IsHSet A x, y: A d: x = y nd': x <> y
inl d = inr nd'
H: Funext A: Type X: IsHSet A x, y: A nd: x <> y d': x = y
inr nd = inl d'
H: Funext A: Type X: IsHSet A x, y: A nd, nd': x <> y
inr nd = inr nd'
H: Funext A: Type X: IsHSet A x, y: A d, d': x = y
inl d = inl d'
apply ap, path_ishprop.
H: Funext A: Type X: IsHSet A x, y: A d: x = y nd': x <> y
inl d = inr nd'
elim (nd' d).
H: Funext A: Type X: IsHSet A x, y: A nd: x <> y d': x = y
inr nd = inl d'
elim (nd d').
H: Funext A: Type X: IsHSet A x, y: A nd, nd': x <> y
inr nd = inr nd'
apply ap, path_forall; intros p; elim (nd p).Defined.(** ** Logical Laws *)(** Various logical laws don't hold constructively as they do classically due to a required use of excluded middle. For us, this means that some laws require further assumptions on the decidability of propositions. *)(** Here we give the dual De Morgan's Law which complements the one given in Iff.v. One direction requires that one of the two propositions be decidable, while the other direction needs no assumption. We state the latter property first, to avoid duplication in the proof. *)