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 Types.Universe.Require Import Metatheory.Core Metatheory.FunextVarieties.Generalizable All Variables.(** * Univalence Implies Functional Extensionality *)SectionUnivalenceImpliesFunext.Context `{ua : Univalence_type}.(** Exponentiation preserves equivalences, i.e., if [e] is an equivalence then so is post-composition by [e]. *)(* Should this go somewhere else? *)
ua: Univalence_type A, B: Type w: A -> B H0: IsEquiv w C: Type
IsEquiv (fung : C -> A => w o g)
ua: Univalence_type A, B: Type w: A -> B H0: IsEquiv w C: Type
IsEquiv (fung : C -> A => w o g)
ua: forallAB : Type, IsEquiv (equiv_path A B) A, B: Type w: A -> B H0: IsEquiv w C: Type
IsEquiv (fun (g : C -> A) (x : C) => w (g x))
refine (isequiv_adjointify
(fun (g:C->A) => w o g)
(fun (g:C->B) => w^-1 o g)
_
_);
intro;
pose (Build_Equiv _ _ w _) as w';
change H0 with (@equiv_isequiv _ _ w');
change w with (@equiv_fun _ _ w');
clearbody w'; clear H0 w;
rewrite <- (@eisretr _ _ (@equiv_path A B) (ua A B) w');
generalize ((@equiv_inv _ _ (equiv_path A B) (ua A B)) w');
intro p;
clear w';
destruct p;
reflexivity.Defined.(** We are ready to prove functional extensionality, starting with the naive non-dependent version. *)
ua: Univalence_type A, B: Type
IsEquiv
(fung : A -> {xy : B * B & fst xy = snd xy} =>
fst o pr1 o g)
ua: Univalence_type A, B: Type
IsEquiv
(fung : A -> {xy : B * B & fst xy = snd xy} =>
fst o pr1 o g)
ua: Univalence_type A, B: Type
IsEquiv
(funx : {xy : B * B & fst xy = snd xy} => fst x.1)
ua: Univalence_type A, B: Type f, g: A -> B p: forallx : A, f x = g x
f = g
(** Consider the following maps. *)
ua: Univalence_type A, B: Type f, g: A -> B p: forallx : A, f x = g x d:= funx : A => ((f x, f x); 1): A -> {xy : B * B & fst xy = snd xy}
f = g
ua: Univalence_type A, B: Type f, g: A -> B p: forallx : A, f x = g x d:= funx : A => ((f x, f x); 1): A -> {xy : B * B & fst xy = snd xy} e:= funx : A => ((f x, g x); p x): A -> {xy : B * B & fst xy = snd xy}
f = g
(** If we compose [d] and [e] with [free_path_target], we get [f] and [g], respectively. So, if we had a path from [d] to [e], we would get one from [f] to [g]. *)
ua: Univalence_type A, B: Type f, g: A -> B p: forallx : A, f x = g x d:= funx : A => ((f x, f x); 1): A -> {xy : B * B & fst xy = snd xy} e:= funx : A => ((f x, g x); p x): A -> {xy : B * B & fst xy = snd xy}
snd o pr1 o d = g
ua: Univalence_type A, B: Type f, g: A -> B p: forallx : A, f x = g x d:= funx : A => ((f x, f x); 1): A -> {xy : B * B & fst xy = snd xy} e:= funx : A => ((f x, g x); p x): A -> {xy : B * B & fst xy = snd xy}
snd o pr1 o d = snd o pr1 o e
ua: Univalence_type A, B: Type f, g: A -> B p: forallx : A, f x = g x d:= funx : A => ((f x, f x); 1): A -> {xy : B * B & fst xy = snd xy} e:= funx : A => ((f x, g x); p x): A -> {xy : B * B & fst xy = snd xy}
d = e
(** Since composition with [src] is an equivalence, we can freely compose with [src]. *)
ua: Univalence_type A, B: Type f, g: A -> B p: forallx : A, f x = g x d:= funx : A => ((f x, f x); 1): A -> {xy : B * B & fst xy = snd xy} e:= funx : A => ((f x, g x); p x): A -> {xy : B * B & fst xy = snd xy} H':= fun (AB : Type)
(xy : A -> {xy : B * B & fst xy = snd xy}) =>
(ap
(fung : A -> {xy : B * B & fst xy = snd xy} =>
fst o pr1 o g))^-1: forall (AB : Type)
(xy : A -> {xy : B * B & fst xy = snd xy}),
(fung : A -> {xy : B * B & fst xy = snd xy} =>
fst o pr1 o g) x =
(fung : A -> {xy : B * B & fst xy = snd xy} =>
fst o pr1 o g) y -> x = y
d = e
ua: Univalence_type A, B: Type f, g: A -> B p: forallx : A, f x = g x d:= funx : A => ((f x, f x); 1): A -> {xy : B * B & fst xy = snd xy} e:= funx : A => ((f x, g x); p x): A -> {xy : B * B & fst xy = snd xy} H':= fun (AB : Type)
(xy : A -> {xy : B * B & fst xy = snd xy}) =>
(ap
(fung : A -> {xy : B * B & fst xy = snd xy} =>
fst o pr1 o g))^-1: forall (AB : Type)
(xy : A -> {xy : B * B & fst xy = snd xy}),
(fung : A -> {xy : B * B & fst xy = snd xy} =>
fst o pr1 o g) x =
(fung : A -> {xy : B * B & fst xy = snd xy} =>
fst o pr1 o g) y -> x = y
(funx : A => fst (d x).1) =
(funx : A => fst (e x).1)
reflexivity.Defined.EndUnivalenceImpliesFunext.(** Now we use this to prove strong dependent funext. Again only the codomain universe must be univalent, but the domain universe must be no larger than it is. Thus practically speaking this means that a univalent universe satisfies funext only for functions between two types in that same universe. *)DefinitionUnivalence_implies_WeakFunext : Univalence_type -> WeakFunext
:= NaiveNondepFunext_implies_WeakFunext o @Univalence_implies_FunextNondep.DefinitionUnivalence_type_implies_Funext_type
`{ua : Univalence_type@{j jplusone} }
: Funext_type@{i j j}
:= NaiveNondepFunext_implies_Funext
(@Univalence_implies_FunextNondep ua).(** The above proof justifies assuming [Univalence -> Funext], which we did axiomatically in [Types/Universe.v]. *)