Timings for Unit.v
(** * Theorems about the unit type *)
Require Import Basics.Overture Basics.Equivalences.
Local Open Scope path_scope.
Local Set Universe Minimization ToSet.
Generalizable Variables A.
Definition eta_unit (z : Unit) : tt = z
:= match z with tt => 1 end.
(** ** Paths *)
(* This is all kind of ridiculous, but it fits the pattern. *)
Definition path_unit_uncurried (z z' : Unit) : Unit -> z = z'
:= fun _ => match z, z' with tt, tt => 1 end.
Definition path_unit (z z' : Unit) : z = z'
:= path_unit_uncurried z z' tt.
Definition eta_path_unit {z z' : Unit} (p : z = z') :
path_unit z z' = p.
Instance isequiv_path_unit (z z' : Unit) : IsEquiv (path_unit_uncurried z z') | 0.
refine (Build_IsEquiv _ _ (path_unit_uncurried z z') (fun _ => tt)
(fun p:z=z' =>
match p in (_ = z') return (path_unit_uncurried z z' tt = p) with
| idpath => match z as z return (path_unit_uncurried z z tt = 1) with
| tt => 1
end
end)
(fun x => match x with tt => 1 end) _).
intros []; destruct z, z'; reflexivity.
Definition equiv_path_unit (z z' : Unit) : Unit <~> (z = z')
:= Build_Equiv _ _ (path_unit_uncurried z z') _.
(** ** Transport *)
(** Is a special case of transporting in a constant fibration. *)
(** ** Universal mapping properties *)
(* The positive universal property *)
Arguments Unit_ind [A] a u : rename.
Instance isequiv_unit_ind `{Funext} (A : Unit -> Type)
: IsEquiv (@Unit_ind A) | 0
:= isequiv_adjointify _
(fun f : forall u:Unit, A u => f tt)
(fun f : forall u:Unit, A u => path_forall (@Unit_ind A (f tt)) f
(fun x => match x with tt => 1 end))
(fun _ => 1).
Instance isequiv_unit_rec `{Funext} (A : Type)
: IsEquiv (@Unit_ind (fun _ => A)) | 0
:= isequiv_unit_ind (fun _ => A).
#[local]
Hint Extern 4 => progress (cbv beta iota) : typeclass_instances.
Definition equiv_unit_rec `{Funext} (A : Type)
: A <~> (Unit -> A)
:= (Build_Equiv _ _ (@Unit_ind (fun _ => A)) _).
(* For various reasons, it is typically more convenient to define functions out of the unit as constant maps, rather than [Unit_ind]. *)
Notation unit_name x := (fun (_ : Unit) => x).
Instance isequiv_unit_name@{i j} `{Funext} (A : Type@{i})
: @IsEquiv@{i j} _ (Unit -> _) (fun (a:A) => unit_name a).
refine (isequiv_adjointify _ (fun f : Unit -> _ => f tt) _ _).
intros f; apply path_forall@{i i j}; intros x.
apply ap@{i i}, path_unit.
(* The negative universal property *)
Definition unit_coind {A : Type} : Unit -> (A -> Unit)
:= fun _ _ => tt.
Instance isequiv_unit_coind `{Funext} (A : Type) : IsEquiv (@unit_coind A) | 0.
refine (isequiv_adjointify _ (fun f => tt) _ _).
apply path_forall; intros x; apply path_unit.
intro x; destruct x; reflexivity.
Definition equiv_unit_coind `{Funext} (A : Type)
: Unit <~> (A -> Unit)
:= Build_Equiv _ _ (@unit_coind A) _.
(** ** Truncation *)
(* The Unit type is contractible *)
Instance contr_unit : Contr Unit | 0 := Build_Contr _ tt (fun t : Unit => match t with tt => 1 end).
(** ** Equivalences *)
(** A contractible type is equivalent to [Unit]. *)
Definition equiv_contr_unit `{Contr A} : A <~> Unit
:= equiv_contr_contr.
(* Conversely, a type equivalent to [Unit] is contractible. We don't make this an instance because Coq would have to guess the equivalence. And when it has a map in mind, it would try to use [isequiv_contr_contr], which would cause a cycle. *)
Definition contr_equiv_unit (A : Type) (f : A <~> Unit) : Contr A
:= contr_equiv' Unit f^-1%equiv.
(** The constant map to [Unit]. We define this so we can get rid of an unneeded universe variable that Coq generates when [const tt] is used in a context that doesn't have [Universe Minimization ToSet] as this file does. If we ever set that globally, then we could get rid of this and remove some imports of this file. *)
Definition const_tt (A : Type) := @const A Unit tt.