-
Notifications
You must be signed in to change notification settings - Fork 141
/
Copy pathFunExtEquiv.agda
208 lines (176 loc) · 9.46 KB
/
FunExtEquiv.agda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
{-# OPTIONS --safe #-}
module Cubical.Functions.FunExtEquiv where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.CartesianKanOps
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Univalence
open import Cubical.Data.Vec.Base
open import Cubical.Data.Vec.NAry
open import Cubical.Data.Nat
open import Cubical.Reflection.StrictEquiv
private
variable
ℓ ℓ₁ ℓ₂ ℓ₃ : Level
-- Function extensionality is an equivalence
module _ {A : Type ℓ} {B : A → I → Type ℓ₁}
{f : (x : A) → B x i0} {g : (x : A) → B x i1} where
funExtEquiv : (∀ x → PathP (B x) (f x) (g x)) ≃ PathP (λ i → ∀ x → B x i) f g
unquoteDef funExtEquiv = defStrictEquiv funExtEquiv funExt funExt⁻
funExtPath : (∀ x → PathP (B x) (f x) (g x)) ≡ PathP (λ i → ∀ x → B x i) f g
funExtPath = ua funExtEquiv
funExtIso : Iso (∀ x → PathP (B x) (f x) (g x)) (PathP (λ i → ∀ x → B x i) f g)
funExtIso = iso funExt funExt⁻ (λ x → refl {x = x}) (λ x → refl {x = x})
-- Function extensionality for binary functions
funExt₂ : {A : Type ℓ} {B : A → Type ℓ₁} {C : (x : A) → B x → I → Type ℓ₂}
{f : (x : A) → (y : B x) → C x y i0}
{g : (x : A) → (y : B x) → C x y i1}
→ ((x : A) (y : B x) → PathP (C x y) (f x y) (g x y))
→ PathP (λ i → ∀ x y → C x y i) f g
funExt₂ p i x y = p x y i
-- Function extensionality for binary functions is an equivalence
module _ {A : Type ℓ} {B : A → Type ℓ₁} {C : (x : A) → B x → I → Type ℓ₂}
{f : (x : A) → (y : B x) → C x y i0}
{g : (x : A) → (y : B x) → C x y i1} where
private
appl₂ : PathP (λ i → ∀ x y → C x y i) f g → ∀ x y → PathP (C x y) (f x y) (g x y)
appl₂ eq x y i = eq i x y
funExt₂Equiv : (∀ x y → PathP (C x y) (f x y) (g x y)) ≃ (PathP (λ i → ∀ x y → C x y i) f g)
unquoteDef funExt₂Equiv = defStrictEquiv funExt₂Equiv funExt₂ appl₂
funExt₂Path : (∀ x y → PathP (C x y) (f x y) (g x y)) ≡ (PathP (λ i → ∀ x y → C x y i) f g)
funExt₂Path = ua funExt₂Equiv
-- Function extensionality for ternary functions
funExt₃ : {A : Type ℓ} {B : A → Type ℓ₁} {C : (x : A) → B x → Type ℓ₂}
{D : (x : A) → (y : B x) → C x y → I → Type ℓ₃}
{f : (x : A) → (y : B x) → (z : C x y) → D x y z i0}
{g : (x : A) → (y : B x) → (z : C x y) → D x y z i1}
→ ((x : A) (y : B x) (z : C x y) → PathP (D x y z) (f x y z) (g x y z))
→ PathP (λ i → ∀ x y z → D x y z i) f g
funExt₃ p i x y z = p x y z i
-- Function extensionality for ternary functions is an equivalence
module _ {A : Type ℓ} {B : A → Type ℓ₁} {C : (x : A) → B x → Type ℓ₂}
{D : (x : A) → (y : B x) → C x y → I → Type ℓ₃}
{f : (x : A) → (y : B x) → (z : C x y) → D x y z i0}
{g : (x : A) → (y : B x) → (z : C x y) → D x y z i1} where
private
appl₃ : PathP (λ i → ∀ x y z → D x y z i) f g → ∀ x y z → PathP (D x y z) (f x y z) (g x y z)
appl₃ eq x y z i = eq i x y z
funExt₃Equiv : (∀ x y z → PathP (D x y z) (f x y z) (g x y z)) ≃ (PathP (λ i → ∀ x y z → D x y z i) f g)
unquoteDef funExt₃Equiv = defStrictEquiv funExt₃Equiv funExt₃ appl₃
funExt₃Path : (∀ x y z → PathP (D x y z) (f x y z) (g x y z)) ≡ (PathP (λ i → ∀ x y z → D x y z i) f g)
funExt₃Path = ua funExt₃Equiv
-- n-ary non-dependent funext
nAryFunExt : {X : Type ℓ} {Y : I → Type ℓ₁} (n : ℕ) (fX : nAryOp n X (Y i0)) (fY : nAryOp n X (Y i1))
→ ((xs : Vec X n) → PathP Y (fX $ⁿ xs) (fY $ⁿ map (λ x → x) xs))
→ PathP (λ i → nAryOp n X (Y i)) fX fY
nAryFunExt zero fX fY p = p []
nAryFunExt (suc n) fX fY p i x = nAryFunExt n (fX x) (fY x) (λ xs → p (x ∷ xs)) i
-- n-ary funext⁻
nAryFunExt⁻ : (n : ℕ) {X : Type ℓ} {Y : I → Type ℓ₁} (fX : nAryOp n X (Y i0)) (fY : nAryOp n X (Y i1))
→ PathP (λ i → nAryOp n X (Y i)) fX fY
→ ((xs : Vec X n) → PathP Y (fX $ⁿ xs) (fY $ⁿ map (λ x → x) xs))
nAryFunExt⁻ zero fX fY p [] = p
nAryFunExt⁻ (suc n) fX fY p (x ∷ xs) = nAryFunExt⁻ n (fX x) (fY x) (λ i → p i x) xs
nAryFunExtEquiv : (n : ℕ) {X : Type ℓ} {Y : I → Type ℓ₁} (fX : nAryOp n X (Y i0)) (fY : nAryOp n X (Y i1))
→ ((xs : Vec X n) → PathP Y (fX $ⁿ xs) (fY $ⁿ map (λ x → x) xs)) ≃ PathP (λ i → nAryOp n X (Y i)) fX fY
nAryFunExtEquiv n {X} {Y} fX fY = isoToEquiv (iso (nAryFunExt n fX fY) (nAryFunExt⁻ n fX fY)
(linv n fX fY) (rinv n fX fY))
where
linv : (n : ℕ) (fX : nAryOp n X (Y i0)) (fY : nAryOp n X (Y i1))
(p : PathP (λ i → nAryOp n X (Y i)) fX fY)
→ nAryFunExt n fX fY (nAryFunExt⁻ n fX fY p) ≡ p
linv zero fX fY p = refl
linv (suc n) fX fY p i j x = linv n (fX x) (fY x) (λ k → p k x) i j
rinv : (n : ℕ) (fX : nAryOp n X (Y i0)) (fY : nAryOp n X (Y i1))
(p : (xs : Vec X n) → PathP Y (fX $ⁿ xs) (fY $ⁿ map (λ x → x) xs))
→ nAryFunExt⁻ n fX fY (nAryFunExt n fX fY p) ≡ p
rinv zero fX fY p i [] = p []
rinv (suc n) fX fY p i (x ∷ xs) = rinv n (fX x) (fY x) (λ ys i → p (x ∷ ys) i) i xs
-- Funext when the domain also depends on the interval
funExtDep : {A : I → Type ℓ} {B : (i : I) → A i → Type ℓ₁}
{f : (x : A i0) → B i0 x} {g : (x : A i1) → B i1 x}
→ ({x₀ : A i0} {x₁ : A i1} (p : PathP A x₀ x₁) → PathP (λ i → B i (p i)) (f x₀) (g x₁))
→ PathP (λ i → (x : A i) → B i x) f g
funExtDep {A = A} {B} {f} {g} h i x =
transp (λ k → B i (coei→i A i x k)) (i ∨ ~ i) (h (λ j → coei→j A i j x) i)
funExtDep⁻ : {A : I → Type ℓ} {B : (i : I) → A i → Type ℓ₁}
{f : (x : A i0) → B i0 x} {g : (x : A i1) → B i1 x}
→ PathP (λ i → (x : A i) → B i x) f g
→ ({x₀ : A i0} {x₁ : A i1} (p : PathP A x₀ x₁) → PathP (λ i → B i (p i)) (f x₀) (g x₁))
funExtDep⁻ q p i = q i (p i)
funExtDepEquiv : {A : I → Type ℓ} {B : (i : I) → A i → Type ℓ₁}
{f : (x : A i0) → B i0 x} {g : (x : A i1) → B i1 x}
→ ({x₀ : A i0} {x₁ : A i1} (p : PathP A x₀ x₁) → PathP (λ i → B i (p i)) (f x₀) (g x₁))
≃ PathP (λ i → (x : A i) → B i x) f g
funExtDepEquiv {A = A} {B} {f} {g} = isoToEquiv isom
where
open Iso
isom : Iso _ _
isom .fun = funExtDep
isom .inv = funExtDep⁻
isom .rightInv q m i x =
transp
(λ k → B i (coei→i A i x (k ∨ m)))
(m ∨ i ∨ ~ i)
(q i (coei→i A i x m))
isom .leftInv h m p i =
transp
(λ k → B i (lemi→i m k))
(m ∨ i ∨ ~ i)
(h (λ j → lemi→j j m) i)
where
lemi→j : ∀ j → coei→j A i j (p i) ≡ p j
lemi→j j k = coePath A (λ i → p i) i j k
lemi→i : PathP (λ m → lemi→j i m ≡ p i) (coei→i A i (p i)) refl
lemi→i m k = coei→i A i (p i) (m ∨ k)
-- Funext for non-dependent functions but where both domain and
-- codomain depend on the interval. In this case we can omit the
-- outer transp in funExtDep.
funExtNonDep : {A : I → Type ℓ} {B : I → Type ℓ₁}
{f : A i0 → B i0} {g : A i1 → B i1}
→ ({x₀ : A i0} {x₁ : A i1} → PathP A x₀ x₁ → PathP B (f x₀) (g x₁))
→ PathP (λ i → A i → B i) f g
funExtNonDep {A = A} h i x = h (λ j → coei→j A i j x) i
funExtNonDep⁻ : {A : I → Type ℓ} {B : I → Type ℓ₁}
{f : A i0 → B i0} {g : A i1 → B i1}
→ PathP (λ i → A i → B i) f g
→ ({x₀ : A i0} {x₁ : A i1} → PathP A x₀ x₁ → PathP B (f x₀) (g x₁))
funExtNonDep⁻ = funExtDep⁻
funExtNonDepEquiv : {A : I → Type ℓ} {B : I → Type ℓ₁}
{f : A i0 → B i0} {g : A i1 → B i1}
→ ({x₀ : A i0} {x₁ : A i1} → PathP A x₀ x₁ → PathP B (f x₀) (g x₁))
≃ PathP (λ i → A i → B i) f g
funExtNonDepEquiv {A = A} = isoToEquiv isom
where
open Iso
isom : Iso _ _
isom .fun = funExtNonDep
isom .inv = funExtNonDep⁻
isom .rightInv q m i x = q i (coei→i A i x m)
isom .leftInv h m p i = h (λ j → lemi→j j m) i
where
lemi→j : ∀ j → coei→j A i j (p i) ≡ p j
lemi→j j k = coePath A (λ i → p i) i j k
heteroHomotopy≃Homotopy : {A : I → Type ℓ} {B : (i : I) → Type ℓ₁}
{f : A i0 → B i0} {g : A i1 → B i1}
→ ({x₀ : A i0} {x₁ : A i1} → PathP A x₀ x₁ → PathP B (f x₀) (g x₁))
≃ ((x₀ : A i0) → PathP B (f x₀) (g (transport (λ i → A i) x₀)))
heteroHomotopy≃Homotopy {A = A} {B} {f} {g} = isoToEquiv isom
where
open Iso
isom : Iso _ _
isom .fun h x₀ = h (isContrSinglP A x₀ .fst .snd)
isom .inv k {x₀} {x₁} p =
subst (λ fib → PathP B (f x₀) (g (fib .fst))) (isContrSinglP A x₀ .snd (x₁ , p)) (k x₀)
isom .rightInv k = funExt λ x₀ →
cong (λ α → subst (λ fib → PathP B (f x₀) (g (fib .fst))) α (k x₀))
(isProp→isSet isPropSinglP (isContrSinglP A x₀ .fst) _
(isContrSinglP A x₀ .snd (isContrSinglP A x₀ .fst))
refl)
∙ transportRefl (k x₀)
isom .leftInv h j {x₀} {x₁} p =
transp
(λ i → PathP B (f x₀) (g (isContrSinglP A x₀ .snd (x₁ , p) (i ∨ j) .fst)))
j
(h (isContrSinglP A x₀ .snd (x₁ , p) j .snd))