475 lines
18 KiB
Text
475 lines
18 KiB
Text
/-
|
||
Copyright (c) 2014 Floris van Doorn. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Author: Floris van Doorn
|
||
Ported from Coq HoTT
|
||
|
||
Theorems about sigma-types (dependent sums)
|
||
-/
|
||
import types.prod
|
||
|
||
open eq sigma sigma.ops equiv is_equiv
|
||
|
||
namespace sigma
|
||
infixr [local] ∘ := function.compose --remove
|
||
variables {A A' : Type} {B : A → Type} {B' : A' → Type} {C : Πa, B a → Type}
|
||
{D : Πa b, C a b → Type}
|
||
{a a' a'' : A} {b b₁ b₂ : B a} {b' : B a'} {b'' : B a''} {u v w : Σa, B a}
|
||
|
||
-- sigma.eta is already used for the eta rule for strict equality
|
||
protected definition peta (u : Σa, B a) : ⟨u.1 , u.2⟩ = u :=
|
||
destruct u (λu1 u2, idp)
|
||
|
||
definition eta2 (u : Σa b, C a b) : ⟨u.1, u.2.1, u.2.2⟩ = u :=
|
||
destruct u (λu1 u2, destruct u2 (λu21 u22, idp))
|
||
|
||
definition eta3 (u : Σa b c, D a b c) : ⟨u.1, u.2.1, u.2.2.1, u.2.2.2⟩ = u :=
|
||
destruct u (λu1 u2, destruct u2 (λu21 u22, destruct u22 (λu221 u222, idp)))
|
||
|
||
definition dpair_eq_dpair (p : a = a') (q : p ▹ b = b') : sigma.mk a b = sigma.mk a' b' :=
|
||
eq.rec_on p (λb b' q, eq.rec_on q idp) b b' q
|
||
|
||
/- In Coq they often have to give u and v explicitly -/
|
||
protected definition path (p : u.1 = v.1) (q : p ▹ u.2 = v.2) : u = v :=
|
||
destruct u
|
||
(λu1 u2, destruct v (λ v1 v2, dpair_eq_dpair))
|
||
p q
|
||
|
||
/- Projections of paths from a total space -/
|
||
|
||
definition path_pr1 (p : u = v) : u.1 = v.1 :=
|
||
ap pr1 p
|
||
|
||
postfix `..1`:(max+1) := path_pr1
|
||
|
||
definition path_pr2 (p : u = v) : p..1 ▹ u.2 = v.2 :=
|
||
eq.rec_on p idp
|
||
--Coq uses the following proof, which only computes if u,v are dpairs AND p is idp
|
||
--(transport_compose B dpr1 p u.2)⁻¹ ⬝ apD dpr2 p
|
||
|
||
postfix `..2`:(max+1) := path_pr2
|
||
|
||
definition dpair_sigma_path (p : u.1 = v.1) (q : p ▹ u.2 = v.2)
|
||
: sigma.mk (sigma.path p q)..1 (sigma.path p q)..2 = ⟨p, q⟩ :=
|
||
begin
|
||
reverts (p, q),
|
||
apply (destruct u), intros (u1, u2),
|
||
apply (destruct v), intros (v1, v2, p), generalize v2, --change to revert
|
||
apply (eq.rec_on p), intros (v2, q),
|
||
apply (eq.rec_on q), apply idp
|
||
end
|
||
|
||
definition sigma_path_pr1 (p : u.1 = v.1) (q : p ▹ u.2 = v.2) : (sigma.path p q)..1 = p :=
|
||
(!dpair_sigma_path)..1
|
||
|
||
definition sigma_path_pr2 (p : u.1 = v.1) (q : p ▹ u.2 = v.2)
|
||
: sigma_path_pr1 p q ▹ (sigma.path p q)..2 = q :=
|
||
(!dpair_sigma_path)..2
|
||
|
||
definition sigma_path_eta (p : u = v) : sigma.path (p..1) (p..2) = p :=
|
||
begin
|
||
apply (eq.rec_on p),
|
||
apply (destruct u), intros (u1, u2),
|
||
apply idp
|
||
end
|
||
|
||
definition transport_dpr1_sigma_path {B' : A → Type} (p : u.1 = v.1) (q : p ▹ u.2 = v.2)
|
||
: transport (λx, B' x.1) (sigma.path p q) = transport B' p :=
|
||
begin
|
||
reverts (p, q),
|
||
apply (destruct u), intros (u1, u2),
|
||
apply (destruct v), intros (v1, v2, p), generalize v2,
|
||
apply (eq.rec_on p), intros (v2, q),
|
||
apply (eq.rec_on q), apply idp
|
||
end
|
||
|
||
/- the uncurried version of sigma_eq. We will prove that this is an equivalence -/
|
||
|
||
definition sigma_path_uncurried (pq : Σ(p : pr1 u = pr1 v), p ▹ (pr2 u) = pr2 v) : u = v :=
|
||
destruct pq sigma.path
|
||
|
||
definition dpair_sigma_path_uncurried (pq : Σ(p : u.1 = v.1), p ▹ u.2 = v.2)
|
||
: sigma.mk (sigma_path_uncurried pq)..1 (sigma_path_uncurried pq)..2 = pq :=
|
||
destruct pq dpair_sigma_path
|
||
|
||
definition sigma_path_pr1_uncurried (pq : Σ(p : u.1 = v.1), p ▹ u.2 = v.2)
|
||
: (sigma_path_uncurried pq)..1 = pq.1 :=
|
||
(!dpair_sigma_path_uncurried)..1
|
||
|
||
definition sigma_path_pr2_uncurried (pq : Σ(p : u.1 = v.1), p ▹ u.2 = v.2)
|
||
: (sigma_path_pr1_uncurried pq) ▹ (sigma_path_uncurried pq)..2 = pq.2 :=
|
||
(!dpair_sigma_path_uncurried)..2
|
||
|
||
definition sigma_path_eta_uncurried (p : u = v) : sigma_path_uncurried (sigma.mk p..1 p..2) = p :=
|
||
!sigma_path_eta
|
||
|
||
definition transport_sigma_path_dpr1_uncurried {B' : A → Type}
|
||
(pq : Σ(p : u.1 = v.1), p ▹ u.2 = v.2)
|
||
: transport (λx, B' x.1) (@sigma_path_uncurried A B u v pq) = transport B' pq.1 :=
|
||
destruct pq transport_dpr1_sigma_path
|
||
|
||
definition is_equiv_sigma_path [instance] (u v : Σa, B a)
|
||
: is_equiv (@sigma_path_uncurried A B u v) :=
|
||
adjointify sigma_path_uncurried
|
||
(λp, ⟨p..1, p..2⟩)
|
||
sigma_path_eta_uncurried
|
||
dpair_sigma_path_uncurried
|
||
|
||
definition equiv_sigma_path (u v : Σa, B a) : (Σ(p : u.1 = v.1), p ▹ u.2 = v.2) ≃ (u = v) :=
|
||
equiv.mk sigma_path_uncurried !is_equiv_sigma_path
|
||
|
||
definition dpair_eq_dpair_pp_pp (p1 : a = a' ) (q1 : p1 ▹ b = b' )
|
||
(p2 : a' = a'') (q2 : p2 ▹ b' = b'') :
|
||
dpair_eq_dpair (p1 ⬝ p2) (transport_pp B p1 p2 b ⬝ ap (transport B p2) q1 ⬝ q2)
|
||
= dpair_eq_dpair p1 q1 ⬝ dpair_eq_dpair p2 q2 :=
|
||
begin
|
||
reverts (b', p2, b'', q1, q2),
|
||
apply (eq.rec_on p1), intros (b', p2),
|
||
apply (eq.rec_on p2), intros (b'', q1),
|
||
apply (eq.rec_on q1), intro q2,
|
||
apply (eq.rec_on q2), apply idp
|
||
end
|
||
|
||
definition sigma_path_pp_pp (p1 : u.1 = v.1) (q1 : p1 ▹ u.2 = v.2)
|
||
(p2 : v.1 = w.1) (q2 : p2 ▹ v.2 = w.2) :
|
||
sigma.path (p1 ⬝ p2) (transport_pp B p1 p2 u.2 ⬝ ap (transport B p2) q1 ⬝ q2)
|
||
= sigma.path p1 q1 ⬝ sigma.path p2 q2 :=
|
||
begin
|
||
reverts (p1, q1, p2, q2),
|
||
apply (destruct u), intros (u1, u2),
|
||
apply (destruct v), intros (v1, v2),
|
||
apply (destruct w), intros,
|
||
apply dpair_eq_dpair_pp_pp
|
||
end
|
||
|
||
reducible dpair_eq_dpair
|
||
definition dpair_eq_dpair_p1_1p (p : a = a') (q : p ▹ b = b') :
|
||
dpair_eq_dpair p q = dpair_eq_dpair p idp ⬝ dpair_eq_dpair idp q :=
|
||
begin
|
||
reverts (b', q),
|
||
apply (eq.rec_on p), intros (b', q),
|
||
apply (eq.rec_on q), apply idp
|
||
end
|
||
|
||
/- path_pr1 commutes with the groupoid structure. -/
|
||
|
||
definition path_pr1_idp (u : Σa, B a) : (refl u)..1 = refl (u.1) := idp
|
||
definition path_pr1_pp (p : u = v) (q : v = w) : (p ⬝ q) ..1 = (p..1) ⬝ (q..1) := !ap_pp
|
||
definition path_pr1_V (p : u = v) : p⁻¹ ..1 = (p..1)⁻¹ := !ap_V
|
||
|
||
/- Applying dpair to one argument is the same as dpair_eq_dpair with reflexivity in the first place. -/
|
||
|
||
definition ap_dpair (q : b₁ = b₂) : ap (sigma.mk a) q = dpair_eq_dpair idp q :=
|
||
eq.rec_on q idp
|
||
|
||
/- Dependent transport is the same as transport along a sigma_eq. -/
|
||
|
||
definition transportD_eq_transport (p : a = a') (c : C a b) :
|
||
p ▹D c = transport (λu, C (u.1) (u.2)) (dpair_eq_dpair p idp) c :=
|
||
eq.rec_on p idp
|
||
|
||
definition sigma_path_eq_sigma_path {p1 q1 : a = a'} {p2 : p1 ▹ b = b'} {q2 : q1 ▹ b = b'}
|
||
(r : p1 = q1) (s : r ▹ p2 = q2) : sigma.path p1 p2 = sigma.path q1 q2 :=
|
||
eq.rec_on r
|
||
proof (λq2 s, eq.rec_on s idp) qed
|
||
q2
|
||
s
|
||
-- begin
|
||
-- reverts (q2, s),
|
||
-- apply (eq.rec_on r), intros (q2, s),
|
||
-- apply (eq.rec_on s), apply idp
|
||
-- end
|
||
|
||
|
||
/- A path between paths in a total space is commonly shown component wise. -/
|
||
definition path_sigma_path {p q : u = v} (r : p..1 = q..1) (s : r ▹ p..2 = q..2) : p = q :=
|
||
begin
|
||
reverts (q, r, s),
|
||
apply (eq.rec_on p),
|
||
apply (destruct u), intros (u1, u2, q, r, s),
|
||
apply concat, rotate 1,
|
||
apply sigma_path_eta,
|
||
apply (sigma_path_eq_sigma_path r s)
|
||
end
|
||
|
||
/- In Coq they often have to give u and v explicitly when using the following definition -/
|
||
definition path_sigma_path_uncurried {p q : u = v}
|
||
(rs : Σ(r : p..1 = q..1), transport (λx, transport B x u.2 = v.2) r p..2 = q..2) : p = q :=
|
||
destruct rs path_sigma_path
|
||
|
||
/- Transport -/
|
||
|
||
/- The concrete description of transport in sigmas (and also 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 also the 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? -/
|
||
|
||
definition transport_eq (p : a = a') (bc : Σ(b : B a), C a b)
|
||
: p ▹ bc = ⟨p ▹ bc.1, p ▹D bc.2⟩ :=
|
||
begin
|
||
apply (eq.rec_on p),
|
||
apply (destruct bc), intros (b, c),
|
||
apply idp
|
||
end
|
||
|
||
/- The special case when the second variable doesn't depend on the first is simpler. -/
|
||
definition transport_eq_deg {B : Type} {C : A → B → Type} (p : a = a') (bc : Σ(b : B), C a b)
|
||
: p ▹ bc = ⟨bc.1, p ▹ bc.2⟩ :=
|
||
begin
|
||
apply (eq.rec_on p),
|
||
apply (destruct bc), intros (b, c),
|
||
apply idp
|
||
end
|
||
|
||
/- Or if the second variable contains a first component that doesn't depend on the first. -/
|
||
|
||
definition transport_eq_4deg {C : A → Type} {D : Π a:A, B a → C a → Type} (p : a = a')
|
||
(bcd : Σ(b : B a) (c : C a), D a b c) : p ▹ bcd = ⟨p ▹ bcd.1, p ▹ bcd.2.1, p ▹D2 bcd.2.2⟩ :=
|
||
begin
|
||
revert bcd,
|
||
apply (eq.rec_on p), intro bcd,
|
||
apply (destruct bcd), intros (b, cd),
|
||
apply (destruct cd), intros (c, d),
|
||
apply idp
|
||
end
|
||
|
||
/- Functorial action -/
|
||
variables (f : A → A') (g : Πa, B a → B' (f a))
|
||
|
||
protected definition functor (u : Σa, B a) : Σa', B' a' :=
|
||
⟨f u.1, g u.1 u.2⟩
|
||
|
||
/- Equivalences -/
|
||
|
||
--TODO: remove explicit arguments of is_equiv
|
||
definition is_equiv_functor [H1 : is_equiv f] [H2 : Π a, is_equiv (g a)]
|
||
: is_equiv (functor f g) :=
|
||
adjointify (functor f g)
|
||
(functor (f⁻¹) (λ(a' : A') (b' : B' a'),
|
||
((g (f⁻¹ a'))⁻¹ (transport B' (retr f a'⁻¹) b'))))
|
||
begin
|
||
intro u',
|
||
apply (destruct u'), intros (a', b'),
|
||
apply (sigma.path (retr f a')),
|
||
-- "rewrite retr (g (f⁻¹ a'))"
|
||
apply concat, apply (ap (λx, (transport B' (retr f a') x))), apply (retr (g (f⁻¹ a'))),
|
||
show retr f a' ▹ (((retr f a') ⁻¹) ▹ b') = b',
|
||
from transport_pV B' (retr f a') b'
|
||
end
|
||
begin
|
||
intro u,
|
||
apply (destruct u), intros (a, b),
|
||
apply (sigma.path (sect f a)),
|
||
show transport B (sect f a) (g (f⁻¹ (f a))⁻¹ (transport B' (retr f (f a)⁻¹) (g a b))) = b,
|
||
from calc
|
||
transport B (sect f a) (g (f⁻¹ (f a))⁻¹ (transport B' (retr f (f a)⁻¹) (g a b)))
|
||
= g a⁻¹ (transport (B' ∘ f) (sect f a) (transport B' (retr f (f a)⁻¹) (g a b)))
|
||
: ap_transport (sect f a) (λ a, g a⁻¹)
|
||
... = g a⁻¹ (transport B' (ap f (sect f a)) (transport B' (retr f (f a)⁻¹) (g a b)))
|
||
: ap (g a⁻¹) !transport_compose
|
||
... = g a⁻¹ (transport B' (ap f (sect f a)) (transport B' (ap f (sect f a)⁻¹) (g a b)))
|
||
: ap (λ x, g a⁻¹ (transport B' (ap f (sect f a)) (transport B' (x⁻¹) (g a b)))) (adj f a)
|
||
... = g a⁻¹ (g a b) : transport_pV
|
||
... = b : sect (g a) b
|
||
end
|
||
-- -- "rewrite ap_transport"
|
||
-- apply concat, apply inverse, apply (ap_transport (sect f a) (λ a, g a⁻¹)),
|
||
-- apply concat, apply (ap (g a⁻¹)),
|
||
-- -- "rewrite transport_compose"
|
||
-- apply concat, apply transport_compose,
|
||
-- -- "rewrite adj"
|
||
-- -- "rewrite transport_pV"
|
||
-- apply sect,
|
||
|
||
definition equiv_functor_of_is_equiv [H1 : is_equiv f] [H2 : Π a, is_equiv (g a)]
|
||
: (Σa, B a) ≃ (Σa', B' a') :=
|
||
equiv.mk (functor f g) !is_equiv_functor
|
||
|
||
context --remove
|
||
irreducible inv function.compose --remove
|
||
definition equiv_functor (Hf : A ≃ A') (Hg : Π a, B a ≃ B' (to_fun Hf a)) :
|
||
(Σa, B a) ≃ (Σa', B' a') :=
|
||
equiv_functor_of_is_equiv (to_fun Hf) (λ a, to_fun (Hg a))
|
||
end --remove
|
||
|
||
definition equiv_functor_id {B' : A → Type} (Hg : Π a, B a ≃ B' a) : (Σa, B a) ≃ Σa, B' a :=
|
||
equiv_functor equiv.refl Hg
|
||
|
||
definition ap_functor_sigma_dpair (p : a = a') (q : p ▹ b = b')
|
||
: ap (sigma.functor f g) (sigma.path p q)
|
||
= sigma.path (ap f p)
|
||
(transport_compose _ f p (g a b)⁻¹ ⬝ ap_transport p g b⁻¹ ⬝ ap (g a') q) :=
|
||
begin
|
||
reverts (b', q),
|
||
apply (eq.rec_on p),
|
||
intros (b', q), apply (eq.rec_on q),
|
||
apply idp
|
||
end
|
||
|
||
definition ap_functor_sigma (p : u.1 = v.1) (q : p ▹ u.2 = v.2)
|
||
: ap (sigma.functor f g) (sigma.path p q)
|
||
= sigma.path (ap f p)
|
||
(transport_compose B' f p (g u.1 u.2)⁻¹ ⬝ ap_transport p g u.2⁻¹ ⬝ ap (g v.1) q) :=
|
||
begin
|
||
reverts (p, q),
|
||
apply (destruct u), intros (a, b),
|
||
apply (destruct v), intros (a', b', p, q),
|
||
apply ap_functor_sigma_dpair
|
||
end
|
||
|
||
/- definition 3.11.9(i): Summing up a contractible family of types does nothing. -/
|
||
open truncation
|
||
definition is_equiv_dpr1 [instance] (B : A → Type) [H : Π a, is_contr (B a)]
|
||
: is_equiv (@pr1 A B) :=
|
||
adjointify pr1
|
||
(λa, ⟨a, !center⟩)
|
||
(λa, idp)
|
||
(λu, sigma.path idp !contr)
|
||
|
||
definition equiv_of_all_contr [H : Π a, is_contr (B a)] : (Σa, B a) ≃ A :=
|
||
equiv.mk pr1 _
|
||
|
||
/- definition 3.11.9(ii): Dually, summing up over a contractible type does nothing. -/
|
||
|
||
definition equiv_center_of_contr (B : A → Type) [H : is_contr A] : (Σa, B a) ≃ B (center A)
|
||
:=
|
||
equiv.mk _ (adjointify
|
||
(λu, contr u.1⁻¹ ▹ u.2)
|
||
(λb, ⟨!center, b⟩)
|
||
(λb, ap (λx, x ▹ b) !path2_contr)
|
||
(λu, sigma.path !contr !transport_pV))
|
||
|
||
/- Associativity -/
|
||
|
||
--this proof is harder than in Coq because we don't have eta definitionally for sigma
|
||
protected definition assoc_equiv (C : (Σa, B a) → Type) : (Σa b, C ⟨a, b⟩) ≃ (Σu, C u) :=
|
||
-- begin
|
||
-- apply equiv.mk,
|
||
-- apply (adjointify (λav, ⟨⟨av.1, av.2.1⟩, av.2.2⟩)
|
||
-- (λuc, ⟨uc.1.1, uc.1.2, !peta⁻¹ ▹ uc.2⟩)),
|
||
-- intro uc, apply (destruct uc), intro u,
|
||
-- apply (destruct u), intros (a, b, c),
|
||
-- apply idp,
|
||
-- intro av, apply (destruct av), intros (a, v),
|
||
-- apply (destruct v), intros (b, c),
|
||
-- apply idp,
|
||
-- end
|
||
equiv.mk _ (adjointify
|
||
(λav, ⟨⟨av.1, av.2.1⟩, av.2.2⟩)
|
||
(λuc, ⟨uc.1.1, uc.1.2, !peta⁻¹ ▹ uc.2⟩)
|
||
proof (λuc, destruct uc (λu, destruct u (λa b c, idp))) qed
|
||
proof (λav, destruct av (λa v, destruct v (λb c, idp))) qed)
|
||
|
||
open prod
|
||
definition assoc_equiv_prod (C : (A × A') → Type) : (Σa a', C (a,a')) ≃ (Σu, C u) :=
|
||
equiv.mk _ (adjointify
|
||
(λav, ⟨(av.1, av.2.1), av.2.2⟩)
|
||
(λuc, ⟨pr₁ (uc.1), pr₂ (uc.1), !prod.peta⁻¹ ▹ uc.2⟩)
|
||
proof (λuc, destruct uc (λu, prod.destruct u (λa b c, idp))) qed
|
||
proof (λav, destruct av (λa v, destruct v (λb c, idp))) qed)
|
||
|
||
/- Symmetry -/
|
||
definition symm_equiv_uncurried (C : A × A' → Type) : (Σa a', C (a, a')) ≃ (Σa' a, C (a, a')) :=
|
||
calc
|
||
(Σa a', C (a, a')) ≃ Σu, C u : assoc_equiv_prod
|
||
... ≃ Σv, C (flip v) : equiv_functor !prod.symm_equiv
|
||
(λu, prod.destruct u (λa a', equiv.refl))
|
||
... ≃ (Σa' a, C (a, a')) : assoc_equiv_prod
|
||
|
||
definition symm_equiv (C : A → A' → Type) : (Σa a', C a a') ≃ (Σa' a, C a a') :=
|
||
symm_equiv_uncurried (λu, C (prod.pr1 u) (prod.pr2 u))
|
||
|
||
definition equiv_prod (A B : Type) : (Σ(a : A), B) ≃ A × B :=
|
||
equiv.mk _ (adjointify
|
||
(λs, (s.1, s.2))
|
||
(λp, ⟨pr₁ p, pr₂ p⟩)
|
||
proof (λp, prod.destruct p (λa b, idp)) qed
|
||
proof (λs, destruct s (λa b, idp)) qed)
|
||
|
||
definition symm_equiv_deg (A B : Type) : (Σ(a : A), B) ≃ Σ(b : B), A :=
|
||
calc
|
||
(Σ(a : A), B) ≃ A × B : equiv_prod
|
||
... ≃ B × A : prod.symm_equiv
|
||
... ≃ Σ(b : B), A : equiv_prod
|
||
|
||
/- ** Universal mapping properties -/
|
||
/- *** The positive universal property. -/
|
||
|
||
section
|
||
open funext
|
||
--in Coq this can be done without function extensionality
|
||
definition is_equiv_sigma_rec [instance] [FUN : funext] (C : (Σa, B a) → Type)
|
||
: is_equiv (@sigma.rec _ _ C) :=
|
||
adjointify _ (λ g a b, g ⟨a, b⟩)
|
||
(λ g, proof path_pi (λu, destruct u (λa b, idp)) qed)
|
||
(λ f, refl f)
|
||
|
||
definition equiv_sigma_rec [FUN : funext] (C : (Σa, B a) → Type)
|
||
: (Π(a : A) (b: B a), C ⟨a, b⟩) ≃ (Πxy, C xy) :=
|
||
equiv.mk sigma.rec _
|
||
|
||
/- *** The negative universal property. -/
|
||
|
||
definition coind_uncurried (fg : Σ(f : Πa, B a), Πa, C a (f a)) (a : A) : Σ(b : B a), C a b
|
||
:= ⟨fg.1 a, fg.2 a⟩
|
||
|
||
definition coind (f : Π a, B a) (g : Π a, C a (f a)) (a : A) : Σ(b : B a), C a b :=
|
||
coind_uncurried ⟨f, g⟩ a
|
||
|
||
--is the instance below dangerous?
|
||
--in Coq this can be done without function extensionality
|
||
definition is_equiv_coind [instance] [FUN : funext] (C : Πa, B a → Type)
|
||
: is_equiv (@coind_uncurried _ _ C) :=
|
||
adjointify _ (λ h, ⟨λa, (h a).1, λa, (h a).2⟩)
|
||
(λ h, proof path_pi (λu, !peta) qed)
|
||
(λfg, destruct fg (λ(f : Π (a : A), B a) (g : Π (x : A), C x (f x)), proof idp qed))
|
||
|
||
definition equiv_coind [FUN : funext] : (Σ(f : Πa, B a), Πa, C a (f a)) ≃ (Πa, Σb, C a b) :=
|
||
equiv.mk coind_uncurried _
|
||
end
|
||
|
||
/- ** Subtypes (sigma types whose second components are hprops) -/
|
||
|
||
/- To prove equality in a subtype, we only need equality of the first component. -/
|
||
definition path_hprop [H : Πa, is_hprop (B a)] (u v : Σa, B a) : u.1 = v.1 → u = v :=
|
||
(sigma_path_uncurried ∘ (@inv _ _ pr1 (@is_equiv_dpr1 _ _ (λp, !succ_is_trunc))))
|
||
|
||
definition is_equiv_path_hprop [instance] [H : Πa, is_hprop (B a)] (u v : Σa, B a)
|
||
: is_equiv (path_hprop u v) :=
|
||
!is_equiv.compose
|
||
|
||
definition equiv_path_hprop [H : Πa, is_hprop (B a)] (u v : Σa, B a) : (u.1 = v.1) ≃ (u = v)
|
||
:=
|
||
equiv.mk !path_hprop _
|
||
|
||
/- truncatedness -/
|
||
definition trunc_sigma [instance] (B : A → Type) (n : trunc_index)
|
||
[HA : is_trunc n A] [HB : Πa, is_trunc n (B a)] : is_trunc n (Σa, B a) :=
|
||
begin
|
||
reverts (A, B, HA, HB),
|
||
apply (trunc_index.rec_on n),
|
||
intros (A, B, HA, HB),
|
||
fapply trunc_equiv',
|
||
apply equiv.symm,
|
||
apply equiv_center_of_contr, apply HA, --should be solved by term synthesis
|
||
apply HB,
|
||
intros (n, IH, A, B, HA, HB),
|
||
fapply is_trunc_succ, intros (u, v),
|
||
fapply trunc_equiv',
|
||
apply equiv_sigma_path,
|
||
apply IH,
|
||
apply succ_is_trunc, assumption,
|
||
intro p,
|
||
show is_trunc n (p ▹ u .2 = v .2), from
|
||
succ_is_trunc n (p ▹ u.2) (v.2),
|
||
end
|
||
|
||
end sigma
|
||
|
||
open truncation sigma
|
||
|
||
namespace prod
|
||
/- truncatedness -/
|
||
definition trunc_prod [instance] (A B : Type) (n : trunc_index)
|
||
[HA : is_trunc n A] [HB : is_trunc n B] : is_trunc n (A × B) :=
|
||
trunc_equiv' n !equiv_prod
|
||
end prod
|