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 dependent products *)
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
Require Export Basics.Trunc (istrunc_forall).LocalOpen Scope path_scope.Generalizable VariablesA B C f g e n.SectionAssumeFunext.Context `{Funext}.(** ** Paths *)(** Paths [p : f = g] in a function type [forall x:X, P x] are equivalent to functions taking values in path types, [H : forall x:X, f x = g x], or concisely, [H : f == g].This equivalence, however, is just the combination of [apD10] and function extensionality [funext], and as such, [path_forall], et seq. are given in the [Overture]: *)(** Now we show how these things compute. *)DefinitionapD10_path_forall `{P : A -> Type}
(f g : forallx, P x) (h : f == g)
: apD10 (path_forall _ _ h) == h
:= apD10 (eisretr apD10 h).Definitioneta_path_forall `{P : A -> Type}
(f g : forallx, P x) (p : f = g)
: path_forall _ _ (apD10 p) = p
:= eissect apD10 p.Definitionpath_forall_1 `{P : A -> Type} (f : forallx, P x)
: (path_forall f f (funx => 1)) = 1
:= eta_path_forall f f 1.(** The identification of the path space of a dependent function space, up to equivalence, is of course just funext. *)Definitionequiv_apD10 {A : Type} (P : A -> Type) fg
: (f = g) <~> (f == g)
:= Build_Equiv _ _ (@apD10 A P f g) _.#[export] Instanceisequiv_path_forall `{P : A -> Type} (f g : forallx, P x)
: IsEquiv (path_forall f g) | 0
:= @isequiv_inverse _ _ (@apD10 A P f g) _.Definitionequiv_path_forall `{P : A -> Type} (f g : forallx, P x)
: (f == g) <~> (f = g)
:= Build_Equiv _ _ (path_forall f g) _.GlobalArguments equiv_path_forall {A%_type_scope P} (f g)%_function_scope.(** ** Path algebra *)
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f == g q: g == h
path_forall f h (funx : A => p x @ q x) =
path_forall f g p @ path_forall g h q
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f == g q: g == h
path_forall f h (funx : A => p x @ q x) =
path_forall f g p @ path_forall g h q
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x
forall (p : f == g) (q : g == h),
path_forall f h (funx : A => p x @ q x) =
path_forall f g p @ path_forall g h q
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f = g
forallq : g == h,
path_forall f h (funx : A => apD10 p x @ q x) =
path_forall f g (apD10 p) @ path_forall g h q
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f = g q: g = h
path_forall f h (funx : A => apD10 p x @ apD10 q x) =
path_forall f g (apD10 p) @ path_forall g h (apD10 q)
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f = g q: g = h
path_forall f h (funx : A => apD10 p x @ apD10 q x) =
path_forall f h (apD10 (p @ q))
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f = g q: g = h
path_forall f h (apD10 (p @ q)) =
path_forall f g (apD10 p) @ path_forall g h (apD10 q)
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f = g q: g = h
path_forall f h (funx : A => apD10 p x @ apD10 q x) =
path_forall f h (apD10 (p @ q))
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f = g q: g = h x: A
apD10 p x @ apD10 q x = apD10 (p @ q) x
symmetry; apply apD10_pp.
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f = g q: g = h
path_forall f h (apD10 (p @ q)) =
path_forall f g (apD10 p) @ path_forall g h (apD10 q)
H: Funext A: Type P: A -> Type f, g, h: forallx : A, P x p: f = g q: g = h
p @ q =
path_forall f g (apD10 p) @ path_forall g h (apD10 q)
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f (funx : A => (p x)^) =
(path_forall f g p)^
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f (funx : A => (p x)^) =
(path_forall f g p)^
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f (funx : A => (p x)^) =
path_forall g f
(funx : A => (apD10 (path_forall f g p) x)^)
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f
(funx : A => (apD10 (path_forall f g p) x)^) =
(path_forall f g p)^
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f (funx : A => (p x)^) =
path_forall g f
(funx : A => (apD10 (path_forall f g p) x)^)
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
(funx : A => (p x)^) =
(funx : A => (apD10 (path_forall f g p) x)^)
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
(funx : A => (apD10 (path_forall f g p) x)^) =
(funx : A => (p x)^)
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
apD10 (path_forall f g p) = p
apply eisretr.
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f
(funx : A => (apD10 (path_forall f g p) x)^) =
(path_forall f g p)^
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f
(funx : A => (apD10 (path_forall f g p) x)^) =
path_forall g f (apD10 (path_forall f g p)^)
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f (apD10 (path_forall f g p)^) =
(path_forall f g p)^
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f
(funx : A => (apD10 (path_forall f g p) x)^) =
path_forall g f (apD10 (path_forall f g p)^)
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
apD10 (path_forall f g p)^ =
(funx : A => (apD10 (path_forall f g p) x)^)
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g x: A
apD10 (path_forall f g p)^ x =
(apD10 (path_forall f g p) x)^
apply apD10_V.
H: Funext A: Type P: A -> Type f, g: forallx : A, P x p: f == g
path_forall g f (apD10 (path_forall f g p)^) =
(path_forall f g p)^
apply eissect.Defined.(** ** Transport *)(** The concrete description of transport in sigmas and 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 the full Id-elim rule by way of "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? *)Definitiontransport_forall
{A : Type} {P : A -> Type} {C : forallx, P x -> Type}
{x1x2 : A} (p : x1 = x2) (f : forally : P x1, C x1 y)
: (transport (funx => forally : P x, C x y) p f)
== (funy =>
transport (C x2) (transport_pV _ _ _) (transportD _ _ p _ (f (p^ # y))))
:= match p with idpath => fun_ => 1end.(** A special case of [transport_forall] where the type [P] does not depend on [A], and so it is just a fixed type [B]. *)Definitiontransport_forall_constant
{AB : Type} {C : A -> B -> Type}
{x1x2 : A} (p : x1 = x2) (f : forally : B, C x1 y)
: (transport (funx => forally : B, C x y) p f)
== (funy => transport (funx => C x y) p (f y))
:= match p with idpath => fun_ => 1end.
H: Funext A, B: Type C: A -> B -> Type x1, x2: A p: x1 = x2 f: forally : B, C x1 y y1, y2: B q: y1 = y2
apD (transport (funx : A => forally : B, C x y) p f)
q =
((ap (transport (C x2) q)
(transport_forall_constant p f y1) @
transport_transport C p q (f y1)) @
ap (transport (funx : A => C x y2) p) (apD f q)) @
(transport_forall_constant p f y2)^
H: Funext A, B: Type C: A -> B -> Type x1, x2: A p: x1 = x2 f: forally : B, C x1 y y1, y2: B q: y1 = y2
apD (transport (funx : A => forally : B, C x y) p f)
q =
((ap (transport (C x2) q)
(transport_forall_constant p f y1) @
transport_transport C p q (f y1)) @
ap (transport (funx : A => C x y2) p) (apD f q)) @
(transport_forall_constant p f y2)^
destruct p, q; reflexivity.Defined.(** ** Maps on paths *)(** The action of maps given by application. *)Definitionap_apply_lD {A} {B : A -> Type} {fg : forallx, B x} (p : f = g) (z : A)
: ap (funf => f z) p = apD10 p z
:= 1.
H: Funext A: Type B: A -> Type C: forallx : A, B x -> Type f, g: forall (x : A) (y : B x), C x y p: f = g z1: A z2: B z1
ap
(funf : forall (x : A) (x0 : B x), C x x0 =>
f z1 z2) p = apD10 (apD10 p z1) z2
H: Funext A: Type B: A -> Type C: forallx : A, B x -> Type f, g: forall (x : A) (y : B x), C x y p: f = g z1: A z2: B z1
ap
(funf : forall (x : A) (x0 : B x), C x x0 =>
f z1 z2) p = apD10 (apD10 p z1) z2
by path_induction.Defined.(** The action of maps given by lambda. *)
H: Funext A, B: Type C: B -> Type x, y: A p: x = y M: A -> forallb : B, C b
ap (fun (a : A) (b : B) => M a b) p =
path_forall (funb : B => (funa : A => M a b) x)
(funb : B => (funa : A => M a b) y)
(funb : B => ap (funa : A => M a b) p)
H: Funext A, B: Type C: B -> Type x, y: A p: x = y M: A -> forallb : B, C b
ap (fun (a : A) (b : B) => M a b) p =
path_forall (funb : B => (funa : A => M a b) x)
(funb : B => (funa : A => M a b) y)
(funb : B => ap (funa : A => M a b) p)
destruct p;
symmetry;
simpl; apply path_forall_1.Defined.(** The action of pre-composition on a path between dependent functions. See also [ap10_ap_precompose] in PathGroupoids.v and [ap_precompose] in Arrow.v. *)Definitionap_precomposeD {BQ : Type} {P : Q -> Type}
{fg : forallq, P q} (h : f = g) (i : B -> Q)
: ap (fun (k : forallq, P q) => k oD i) h
= path_forall (f oD i) (g oD i) (apD10 h oD i)
:= ap_lambdaD _ _.(** ** Dependent paths *)(** Usually, a dependent path over [p:x1=x2] in [P:A->Type] between [y1:P x1] and [y2:P x2] is a path [transport P p y1 = y2] in [P x2]. However, when [P] is a function space, these dependent paths have a more convenient description: rather than transporting the argument of [y1] forwards and backwards, we transport only forwards but on both sides of the equation, yielding a "naturality square". *)
H: Funext A: Type B: A -> Type C: foralla : A, B a -> Type x1, x2: A p: x1 = x2 f: forally1 : B x1, C x1 y1 g: forally2 : B x2, C x2 y2
(forally1 : B x1,
transportD B C p y1 (f y1) = g (transport B p y1)) <~>
transport (funx : A => forally : B x, C x y) p f = g
H: Funext A: Type B: A -> Type C: foralla : A, B a -> Type x1, x2: A p: x1 = x2 f: forally1 : B x1, C x1 y1 g: forally2 : B x2, C x2 y2
(forally1 : B x1,
transportD B C p y1 (f y1) = g (transport B p y1)) <~>
transport (funx : A => forally : B x, C x y) p f = g
H: Funext A: Type B: A -> Type C: foralla : A, B a -> Type x1: A f, g: forally2 : B x1, C x1 y2
(forally1 : B x1,
transportD B C 1 y1 (f y1) = g (transport B 1 y1)) <~>
transport (funx : A => forally : B x, C x y) 1 f = g
apply equiv_path_forall.Defined.
H: Funext A, B: Type C: A -> B -> Type x1, x2: A p: x1 = x2 f: forally1 : B, C x1 y1 g: forally2 : B, C x2 y2
(forally1 : B,
transport (funx : A => C x y1) p (f y1) = g y1) <~>
transport (funx : A => forally : B, C x y) p f = g
H: Funext A, B: Type C: A -> B -> Type x1, x2: A p: x1 = x2 f: forally1 : B, C x1 y1 g: forally2 : B, C x2 y2
(forally1 : B,
transport (funx : A => C x y1) p (f y1) = g y1) <~>
transport (funx : A => forally : B, C x y) p f = g
H: Funext A, B: Type C: A -> B -> Type x1: A f, g: forally2 : B, C x1 y2
(forally1 : B,
transport (funx : A => C x y1) 1 (f y1) = g y1) <~>
transport (funx : A => forally : B, C x y) 1 f = g
apply equiv_path_forall.Defined.(** ** Functorial action *)(** The functoriality of [forall] is slightly subtle: it is contravariant in the domain type and covariant in the codomain, but the codomain is dependent on the domain. *)Definitionfunctor_forall `{P : A -> Type} `{Q : B -> Type}
(f0 : B -> A) (f1 : forallb:B, P (f0 b) -> Q b)
: (foralla:A, P a) -> (forallb:B, Q b)
:= (fungb => f1 _ (g (f0 b))).
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g, g': foralla : A, P a h: g == g'
ap (functor_forall f0 f1) (path_forall g g' h) =
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g' (f0 b)))
(funb : B => ap (f1 b) (h (f0 b)))
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g, g': foralla : A, P a h: g == g'
ap (functor_forall f0 f1) (path_forall g g' h) =
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g' (f0 b)))
(funb : B => ap (f1 b) (h (f0 b)))
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g, g': foralla : A, P a
forallh : g == g',
ap (functor_forall f0 f1) (path_forall g g' h) =
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g' (f0 b)))
(funb : B => ap (f1 b) (h (f0 b)))
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g, g': foralla : A, P a h: g = g'
ap (functor_forall f0 f1) (path_forall g g' (apD10 h)) =
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g' (f0 b)))
(funb : B => ap (f1 b) (apD10 h (f0 b)))
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g: foralla : A, P a
ap (functor_forall f0 f1) (path_forall g g (apD10 1)) =
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g (f0 b)))
(funb : B => ap (f1 b) (apD10 1 (f0 b)))
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g: foralla : A, P a
ap (functor_forall f0 f1) (path_forall g g (apD10 1)) =
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g (f0 b))) (funb : B => 1)
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g: foralla : A, P a
ap (functor_forall f0 f1) (path_forall g g (apD10 1)) =
1
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g: foralla : A, P a
1 =
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g (f0 b))) (funb : B => 1)
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g: foralla : A, P a
ap (functor_forall f0 f1) (path_forall g g (apD10 1)) =
1
exact (ap (ap (functor_forall f0 f1)) (path_forall_1 g)).
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g: foralla : A, P a
1 =
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g (f0 b))) (funb : B => 1)
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: B -> A f1: forallb : B, P (f0 b) -> Q b g: foralla : A, P a
path_forall (funb : B => f1 b (g (f0 b)))
(funb : B => f1 b (g (f0 b))) (funb : B => 1) = 1
apply path_forall_1.Defined.Definitionfunctor_forall_compose
`{P : A -> Type} `{Q : B -> Type} `{R : C -> Type}
(f0 : B -> A) (f1 : forallb:B, P (f0 b) -> Q b)
(g0 : C -> B) (g1 : forallc:C, Q (g0 c) -> R c)
(k : foralla, P a)
: functor_forall g0 g1 (functor_forall f0 f1 k) == functor_forall (f0 o g0) (func => g1 c o f1 (g0 c)) k
:= funa => 1.(** Some special cases appear when one or the other of the maps are equivalences. *)Definitionfunctor_forall_id `{P : A -> Type} `{Q : A -> Type}
(f1 : foralla:A, P a -> Q a)
: (foralla:A, P a) -> (foralla:A, Q a)
:= functor_forall idmap f1.Definitionfunctor_forall_pb {AB : Type} `{P : A -> Type}
(f0 : B -> A)
: (foralla:A, P a) -> (forallb:B, P (f0 b))
:= functor_forall f0 (fun_ => idmap).(** If [f0] is an equivalence, then we can simply apply [functor_forall] to its inverse. However, in this case it is sometimes more convenient to place the substitution on the other side of [f1]. *)
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: A -> B IsEquiv0: IsEquiv f0 f1: foralla : A, P a -> Q (f0 a)
(foralla : A, P a) -> forallb : B, Q b
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: A -> B IsEquiv0: IsEquiv f0 f1: foralla : A, P a -> Q (f0 a)
(foralla : A, P a) -> forallb : B, Q b
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: A -> B IsEquiv0: IsEquiv f0 f1: foralla : A, P a -> Q (f0 a)
forallb : B, P (f0^-1 b) -> Q b
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: A -> B IsEquiv0: IsEquiv f0 f1: foralla : A, P a -> Q (f0 a) b: B u: P (f0^-1 b)
Q b
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f0: A -> B IsEquiv0: IsEquiv f0 f1: foralla : A, P a -> Q (f0 a) b: B u: P (f0^-1 b)
Q (f0 (f0^-1 b))
exact (f1 _ u).Defined.Definitionfunctor_forall_equiv_pb {AB : Type} `{Q : B -> Type}
(f0 : A -> B) `{!IsEquiv f0}
: (foralla:A, Q (f0 a)) -> (forallb:B, Q b)
:= functor_forall_equiv f0 (fun_ => idmap).(** Since there's a nontrivial transport here, it's useful to have a computation lemma. *)
H: Funext A, B: Type P: B -> Type f: A -> B IsEquiv0: IsEquiv f h: foralla : A, P (f a)
foralla : A, functor_forall_equiv_pb f h (f a) = h a
H: Funext A, B: Type P: B -> Type f: A -> B IsEquiv0: IsEquiv f h: foralla : A, P (f a)
foralla : A, functor_forall_equiv_pb f h (f a) = h a
H: Funext A, B: Type P: B -> Type f: A -> B IsEquiv0: IsEquiv f h: foralla : A, P (f a) a: A
functor_forall_equiv_pb f h (f a) =
transport P (ap f (eissect f a)) (h (f^-1 (f a)))
srapply ap10; apply ap; apply eisadj.Defined.(** ** Equivalences *)(** If *both* maps in [functor_forall] are equivalences, then so is the output. *)
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b)
IsEquiv (functor_forall f g)
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b)
IsEquiv (functor_forall f g)
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b)
(forallb : B, Q b) -> foralla : A, P a
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b)
functor_forall f g o ?g == idmap
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b)
?g o functor_forall f g == idmap
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b)
(forallb : B, Q b) -> foralla : A, P a
exact (functor_forall (f^-1)
(fun (x : A) (y : Q (f^-1 x)) => eisretr f x # (g (f^-1 x))^-1 y)).
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b)
functor_forall f g
o functor_forall f^-1
(fun (x : A) (y : Q (f^-1 x)) =>
transport P (eisretr f x) ((g (f^-1 x))^-1 y)) ==
idmap
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: forallb : B, Q b
functor_forall f g
(functor_forall f^-1
(fun (x : A) (y : Q (f^-1 x)) =>
transport P (eisretr f x) ((g (f^-1 x))^-1 y)) h) =
h
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: forallb : B, Q b b: B
g b
(transport P (eisretr f (f b))
((g (f^-1 (f b)))^-1 (h (f^-1 (f b))))) = h b
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: forallb : B, Q b b: B
g b
(transport P (ap f (eissect f b))
((g (f^-1 (f b)))^-1 (h (f^-1 (f b))))) = h b
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: forallb : B, Q b b: B
g b
(transport (funx : B => P (f x)) (eissect f b)
((g (f^-1 (f b)))^-1 (h (f^-1 (f b))))) = h b
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: forallb : B, Q b b: B
transport Q (eissect f b)
(g (f^-1 (f b))
((g (f^-1 (f b)))^-1 (h (f^-1 (f b))))) = h b
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: forallb : B, Q b b: B
transport Q (eissect f b) (h (f^-1 (f b))) = h b
apply apD.
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b)
functor_forall f^-1
(fun (x : A) (y : Q (f^-1 x)) =>
transport P (eisretr f x) ((g (f^-1 x))^-1 y))
o functor_forall f g == idmap
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: foralla : A, P a
functor_forall f^-1
(fun (x : A) (y : Q (f^-1 x)) =>
transport P (eisretr f x) ((g (f^-1 x))^-1 y))
(functor_forall f g h) = h
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: foralla : A, P a a: A
transport P (eisretr f a)
((g (f^-1 a))^-1 (g (f^-1 a) (h (f (f^-1 a))))) =
h a
H: Funext A: Type P: A -> Type B: Type Q: B -> Type f: B -> A H0: IsEquiv f g: forallx : B, P (f x) -> Q x H1: forallb : B, IsEquiv (g b) h: foralla : A, P a a: A
transport P (eisretr f a) (h (f (f^-1 a))) = h a
apply apD.Defined.Definitionequiv_functor_forall `{P : A -> Type} `{Q : B -> Type}
(f : B -> A) `{IsEquiv B A f}
(g : forallb, P (f b) -> Q b)
`{forallb, @IsEquiv (P (f b)) (Q b) (g b)}
: (foralla, P a) <~> (forallb, Q b)
:= Build_Equiv _ _ (functor_forall f g) _.Definitionequiv_functor_forall' `{P : A -> Type} `{Q : B -> Type}
(f : B <~> A) (g : forallb, P (f b) <~> Q b)
: (foralla, P a) <~> (forallb, Q b)
:= equiv_functor_forall f g.Definitionequiv_functor_forall_id `{P : A -> Type} `{Q : A -> Type}
(g : foralla, P a <~> Q a)
: (foralla, P a) <~> (foralla, Q a)
:= equiv_functor_forall (equiv_idmap A) g.Definitionequiv_functor_forall_pb {AB : Type} {P : A -> Type}
(f : B <~> A)
: (foralla, P a) <~> (forallb, P (f b))
:= equiv_functor_forall' (Q := P o f) f (funb => equiv_idmap).(** Similarly, we have a version of [functor_forall_equiv] that acts on on equivalences both upstairs and downstairs. *)Definitionequiv_functor_forall_covariant
`{P : A -> Type} `{Q : B -> Type}
(f : A <~> B) (g : foralla, P a <~> Q (f a))
: (foralla, P a) <~> (forallb, Q b)
:= (equiv_functor_forall' f (funa => (g a)^-1%equiv))^-1.
H: Funext A: Type P: A -> Type B: Type Q: B -> Type C: Type R: C -> Type f0: A <~> B f1: foralla : A, P a <~> Q (f0 a) g0: B <~> C g1: forallb : B, Q b <~> R (g0 b) h: foralla : A, P a
equiv_functor_forall_covariant g0 g1
(equiv_functor_forall_covariant f0 f1 h) ==
equiv_functor_forall_covariant (g0 oE f0)
(funa : A => g1 (f0 a) oE f1 a) h
H: Funext A: Type P: A -> Type B: Type Q: B -> Type C: Type R: C -> Type f0: A <~> B f1: foralla : A, P a <~> Q (f0 a) g0: B <~> C g1: forallb : B, Q b <~> R (g0 b) h: foralla : A, P a
equiv_functor_forall_covariant g0 g1
(equiv_functor_forall_covariant f0 f1 h) ==
equiv_functor_forall_covariant (g0 oE f0)
(funa : A => g1 (f0 a) oE f1 a) h
H: Funext A: Type P: A -> Type B: Type Q: B -> Type C: Type R: C -> Type f0: A <~> B f1: foralla : A, P a <~> Q (f0 a) g0: B <~> C g1: forallb : B, Q b <~> R (g0 b) h: foralla : A, P a
equiv_functor_forall_covariant g0 g1
(equiv_functor_forall_covariant f0 f1 h) =
equiv_functor_forall_covariant (g0 oE f0)
(funa : A => g1 (f0 a) oE f1 a) h
H: Funext A: Type P: A -> Type B: Type Q: B -> Type C: Type R: C -> Type f0: A <~> B f1: foralla : A, P a <~> Q (f0 a) g0: B <~> C g1: forallb : B, Q b <~> R (g0 b) h: foralla : A, P a
(equiv_functor_forall' f0 (funa : A => (f1 a)^-1)
oE equiv_functor_forall' g0 (funa : B => (g1 a)^-1))^-1
h =
equiv_functor_forall_covariant (g0 oE f0)
(funa : A => g1 (f0 a) oE f1 a) h
H: Funext A: Type P: A -> Type B: Type Q: B -> Type C: Type R: C -> Type f0: A <~> B f1: foralla : A, P a <~> Q (f0 a) g0: B <~> C g1: forallb : B, Q b <~> R (g0 b) h: foralla : C, R a
equiv_functor_forall' (g0 oE f0)
(funa : A => (g1 (f0 a) oE f1 a)^-1%equiv) h =
(equiv_functor_forall' f0 (funa : A => (f1 a)^-1)
oE equiv_functor_forall' g0 (funa : B => (g1 a)^-1))
h
H: Funext A: Type P: A -> Type B: Type Q: B -> Type C: Type R: C -> Type f0: A <~> B f1: foralla : A, P a <~> Q (f0 a) g0: B <~> C g1: forallb : B, Q b <~> R (g0 b) h: foralla : C, R a c: A
equiv_functor_forall' (g0 oE f0)
(funa : A => (g1 (f0 a) oE f1 a)^-1%equiv) h c =
(equiv_functor_forall' f0 (funa : A => (f1 a)^-1)
oE equiv_functor_forall' g0 (funa : B => (g1 a)^-1))
h c
symmetry; rapply functor_forall_compose.Defined.(** ** Functoriality on logical equivalences *)(** At least over a fixed base *)Definitioniff_functor_forall {A : Type} {PQ : A -> Type}
(f : foralla, P a <-> Q a)
: (foralla, P a) <-> (foralla, Q a)
:= (functor_forall idmap (funa => fst (f a)),
functor_forall idmap (funa => snd (f a))).(** ** Two variable versions for function extensionality. *)Definitionequiv_path_forall11 {A : Type} {B : A -> Type} {P : foralla : A, B a -> Type} (fg : forallab, P a b)
: (forall (a : A) (b : B a), f a b = g a b) <~> f = g
:= (equiv_path_forall f g) oE (equiv_functor_forall_id (funa => equiv_path_forall (f a) (g a))).Definitionpath_forall11 {A : Type} {B : A -> Type} {P : foralla : A, B a -> Type} (fg : forallab, P a b)
: (forallxy, f x y = g x y) -> f = g
:= equiv_path_forall11 f g.#[export] Instanceisequiv_path_forall11 {A : Type} {B : A -> Type} `{P : foralla : A, B a -> Type} (f g : forallab, P a b)
: IsEquiv (path_forall11 f g) | 0
:= _.GlobalArguments equiv_path_forall11 {A B}%_type_scope {P} (f g)%_function_scope.GlobalArguments path_forall11 {A B}%_type_scope {P} (f g)%_function_scope _.(** ** Truncatedness: any dependent product of n-types is an n-type: see [contr_forall] and [istrunc_forall] in Basics.Trunc. *)(** ** Contractibility: A product over a contractible type is equivalent to the fiber over the center. *)
H: Funext A: Type Contr0: Contr A P: A -> Type
(foralla : A, P a) <~> P (center A)
H: Funext A: Type Contr0: Contr A P: A -> Type
(foralla : A, P a) <~> P (center A)
H: Funext A: Type Contr0: Contr A P: A -> Type
P (center A) -> foralla : A, P a
H: Funext A: Type Contr0: Contr A P: A -> Type
(funf : foralla : A, P a => f (center A)) o ?g ==
idmap
H: Funext A: Type Contr0: Contr A P: A -> Type
?g o (funf : foralla : A, P a => f (center A)) ==
idmap
H: Funext A: Type Contr0: Contr A P: A -> Type
P (center A) -> foralla : A, P a
intros p a; exact (transport P (path_contr _ _) p).
H: Funext A: Type Contr0: Contr A P: A -> Type
(funf : foralla : A, P a => f (center A))
o (fun (p : P (center A)) (a : A) =>
transport P (path_contr (center A) a) p) == idmap
H: Funext A: Type Contr0: Contr A P: A -> Type p: P (center A)
transport P (path_contr (center A) (center A)) p = p
H: Funext A: Type Contr0: Contr A P: A -> Type p: P (center A)
path_contr (center A) (center A) = 1
apply path_contr.
H: Funext A: Type Contr0: Contr A P: A -> Type
(fun (p : P (center A)) (a : A) =>
transport P (path_contr (center A) a) p)
o (funf : foralla : A, P a => f (center A)) == idmap
H: Funext A: Type Contr0: Contr A P: A -> Type f: foralla : A, P a a: A
transport P (path_contr (center A) a) (f (center A)) =
f a
apply apD.Defined.EndAssumeFunext.(** ** Symmetry of curried arguments *)(** Using the standard Haskell name for this, as itβs a handy utility function.Note: not sure if [P] will usually be deducible, or whether it would be better explicit. *)Definitionflip `{P : A -> B -> Type}
: (forallab, P a b) -> (forallba, P a b)
:= funfba => f a b.Arguments flip {A B P} f b a /.
A, B: Type P: A -> B -> Type
IsEquiv flip
A, B: Type P: A -> B -> Type
IsEquiv flip
A, B: Type P: A -> B -> Type flip_P:= flip: (forall (a : A) (b : B), P a b) ->
forall (b : B) (a : A), P a b
IsEquiv flip_P
A, B: Type P: A -> B -> Type flip_P:= flip: (forall (a : A) (b : B), P a b) ->
forall (b : B) (a : A), P a b flip_P_inv:= flip: (forall (a : B) (b : A), flip P a b) ->
forall (b : A) (a : B), flip P a b
IsEquiv flip_P
A, B: Type P: A -> B -> Type flip_P:= flip: (forall (a : A) (b : B), P a b) ->
forall (b : B) (a : A), P a b flip_P_inv:= flip: (forall (a : B) (b : A), flip P a b) ->
forall (b : A) (a : B), flip P a b flip_P_is_sect:= (funf : forall (a : A) (b : B), P a b
=> 1)
:
flip_P_inv o flip_P == idmap: flip_P_inv o flip_P == idmap
IsEquiv flip_P
A, B: Type P: A -> B -> Type flip_P:= flip: (forall (a : A) (b : B), P a b) ->
forall (b : B) (a : A), P a b flip_P_inv:= flip: (forall (a : B) (b : A), flip P a b) ->
forall (b : A) (a : B), flip P a b flip_P_is_sect:= (funf : forall (a : A) (b : B), P a b
=> 1)
:
flip_P_inv o flip_P == idmap: flip_P_inv o flip_P == idmap flip_P_is_retr:= (fung : forall (a : B) (b : A),
flip P a b => 1)
:
flip_P o flip_P_inv == idmap: flip_P o flip_P_inv == idmap
IsEquiv flip_P
A, B: Type P: A -> B -> Type flip_P:= flip: (forall (a : A) (b : B), P a b) ->
forall (b : B) (a : A), P a b flip_P_inv:= flip: (forall (a : B) (b : A), flip P a b) ->
forall (b : A) (a : B), flip P a b flip_P_is_sect:= (funf : forall (a : A) (b : B), P a b
=> 1)
:
flip_P_inv o flip_P == idmap: flip_P_inv o flip_P == idmap flip_P_is_retr:= (fung : forall (a : B) (b : A),
flip P a b => 1)
:
flip_P o flip_P_inv == idmap: flip_P o flip_P_inv == idmap
forallx : forall (b : A) (a : B), flip P a b,
flip_P_is_retr (flip_P x) =
ap flip_P (flip_P_is_sect x)
A, B: Type P: A -> B -> Type flip_P:= flip: (forall (a : A) (b : B), P a b) ->
forall (b : B) (a : A), P a b flip_P_inv:= flip: (forall (a : B) (b : A), flip P a b) ->
forall (b : A) (a : B), flip P a b flip_P_is_sect:= (funf : forall (a : A) (b : B), P a b
=> 1)
:
flip_P_inv o flip_P == idmap: flip_P_inv o flip_P == idmap flip_P_is_retr:= (fung : forall (a : B) (b : A),
flip P a b => 1)
:
flip_P o flip_P_inv == idmap: flip_P o flip_P_inv == idmap g: forall (b : A) (a : B), flip P a b
flip_P_is_retr (flip_P g) =
ap flip_P (flip_P_is_sect g)
exact1.Defined.Definitionequiv_flip `(P : A -> B -> Type)
: (forallab, P a b) <~> (forallba, P a b)
:= Build_Equiv _ _ (@flip _ _ P) _.