-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTheorems.lean
More file actions
605 lines (580 loc) · 28 KB
/
Theorems.lean
File metadata and controls
605 lines (580 loc) · 28 KB
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
import TabularTypes.«F⊗⊕ω».Lemmas.Value
import TabularTypes.«F⊗⊕ω».Lemmas.Term
import TabularTypes.«F⊗⊕ω».Semantics.Term
macro "rwomega" equality:term : tactic => `(tactic | (have _eq : $equality := (by omega); rw [_eq]; clear _eq))
namespace TabularTypes.«F⊗⊕ω»
open Std
private
theorem _root_.Membership.mem.inc {r : Range} (h : i ∈ r) : i ∈ { r with stop := r.stop + 1 } :=
⟨h.lower, Nat.lt_add_right _ h.upper, h.step⟩
private
theorem progress.sandwich {f : Nat → α} (h : i < n) : [0:n].map (fun j => f j) =
[:i].map (fun j => f j) ++
f i :: [(i + 1) - (i + 1):n - (i + 1)].map (fun j => f (j + (i + 1))) := by
rw [← List.singleton_append, Range.map_shift (Nat.le_refl _)]
have : [f i] = List.map (fun j => f j) [i:i + 1] := by
rw [Range.toList, if_pos (Nat.lt_succ_self _), Range.toList,
if_neg (Nat.not_lt_of_le (Nat.le_refl _)), List.map, List.map]
rw [this]
rw [Range.map_append (Nat.le_succ _) (Nat.succ_le_of_lt h),
Range.map_append (Nat.zero_le _) (Nat.le_of_lt h)]
private
theorem progress.fold {E : Nat → Term} (EtyA : ∀ i ∈ [0:n], [[ε ⊢ E@i : A@i]])
(h : ∀ i ∈ [0:n], (∃ E', [[E@i -> E']]) ∨ (E i).IsValue) :
(∃ i ∈ [0:n], (∀ j ∈ [0:i], (E j).IsValue) ∧ ∃ E', [[E@i -> E']]) ∨
(∀ i ∈ [0:n], (E i).IsValue) := by
induction n
· case zero =>
right
intro _ ⟨_, lt_zero, _⟩
contradiction
· case succ j ih' => match ih' (fun j mem => EtyA j mem.inc) (fun j mem => h j mem.inc) with
| .inl ⟨i, mem, ⟨E'', toE''⟩⟩ => exact .inl ⟨i, mem.inc, ⟨E'', toE''⟩⟩
| .inr IsValue =>
have jmem : j ∈ [0:j + 1] := ⟨Nat.zero_le _, Nat.lt_succ_self _, Nat.mod_one _⟩
match h j jmem with
| .inl ⟨E'', toE''⟩ => exact .inl ⟨j, jmem, ⟨IsValue, ⟨E'', toE''⟩⟩⟩
| .inr jIsValue =>
right
intro i mem
by_cases i = j
· case pos h =>
rw [h]
exact jIsValue
· case neg h =>
exact IsValue i
⟨Nat.zero_le _, Nat.lt_of_le_of_ne (Nat.le_of_lt_succ mem.upper) h, Nat.mod_one _⟩
local instance : Inhabited Value where
default := ⟨.prodIntro [], .prodIntro nofun⟩
in
theorem progress (EtyA : [[ε ⊢ E : A]]) : (∃ E', [[E -> E']]) ∨ E.IsValue := by
generalize Δeq : Environment.empty = Δ at EtyA
induction EtyA <;> cases Δeq
· case var xinε => cases xinε
· case lam => exact .inr .lam
· case app E' A' B F E'tyA'arrB _ ih₁ ih₂ => match ih₁ rfl with
| .inl ⟨E'', E'toE''⟩ => exact .inl <| .intro _ <| .appL E'toE''
| .inr E'IsValue => match ih₂ rfl with
| .inl ⟨F', FtoF'⟩ => exact .inl <| .intro _ <| .appR (V := ⟨E', E'IsValue⟩) FtoF'
| .inr FIsValue =>
let VE' : Value := ⟨E', E'IsValue⟩
have : E' = VE'.1 := rfl
have A'Blc := E'tyA'arrB.TypeVarLocallyClosed_of
have ⟨_, _, VE'eq⟩ := VE'.canonical_form_of_arr E'tyA'arrB
rw [this, VE'eq]
exact .inl <| .intro _ <| .lamApp (V := ⟨F, FIsValue⟩)
· case typeLam => exact .inr .typeLam
· case typeApp E' K _ _ E'ty _ ih => match ih rfl with
| .inl ⟨E'', E'toE''⟩ => exact .inl <| .intro _ <| .typeApp E'toE''
| .inr E'IsValue =>
let V : Value := ⟨E', E'IsValue⟩
have : E' = V.1 := rfl
have ⟨_, _, Veq⟩ := V.canonical_form_of_forall E'ty
rw [this, Veq]
exact .inl <| .intro _ <| .typeLamApp
· case prodIntro n E' A b h wf E'ty ih => match progress.fold E'ty (fun i mem => ih i mem rfl) with
| .inl ⟨i, ⟨_, iltn, _⟩, IsValue, E'', toE''⟩ =>
let V j : Value := if h' : j < i then
⟨E' j, IsValue j ⟨Nat.zero_le _, h', Nat.mod_one _⟩⟩
else
default
rw [progress.sandwich iltn, Range.map_eq_of_eq_of_mem'' (fun j jmem => by
show E' j = (V j).val
dsimp only [V]
rw [dif_pos jmem.upper]
), Nat.sub_self]
exact .inl <| .intro _ <| .prodIntro toE''
| .inr IsValue =>
exact .inr <| .prodIntro fun E Emem => by
have ⟨i, imem, Eeq⟩ := Range.mem_of_mem_map Emem
rw [Eeq]
exact IsValue i imem
· case prodElim E' n _ _ i mem E'ty ih => match ih rfl with
| .inl ⟨E'', E'toE''⟩ => exact .inl <| .intro _ <| .prodElim E'toE''
| .inr E'IsValue =>
let V : Value := ⟨E', E'IsValue⟩
have : E' = V.1 := rfl
have ⟨_, Veq, h⟩ := V.canonical_form_of_prod E'ty
rw [this, Veq]
exact .inl <| .intro _ <| .prodElimIntro mem
· case sumIntro ih => match ih rfl with
| .inl ⟨E', toE'⟩ => exact .inl <| .intro _ <| .sumIntro toE'
| .inr E'IsValue => exact .inr <| .sumIntro E'IsValue
· case sumElim E' n As _ F _ E'ty Fty Fki ih₁ ih₂ => match ih₁ rfl with
| .inl ⟨E'', E'toE''⟩ => exact .inl <| .intro _ <| .sumElimL E'toE''
| .inr E'IsValue =>
let VE' : Value := ⟨E', E'IsValue⟩
have ⟨n', mem, VE'', VE'_eq, _⟩ := VE'.canonical_form_of_sum E'ty
cases VE'_eq
match progress.fold Fty (fun i mem => ih₂ i mem rfl) with
| .inl ⟨j, ⟨_, jltn, _⟩, IsValue, F', toF'⟩ =>
let VF k : Value := if h' : k < j then
⟨F k, IsValue k ⟨Nat.zero_le _, h', Nat.mod_one _⟩⟩
else
default
rw [progress.sandwich jltn, Range.map_eq_of_eq_of_mem'' (fun j jmem => by
show F j = (VF j).val
dsimp only [VF]
rw [dif_pos jmem.upper]
), Nat.sub_self]
exact .inl <| .intro _ <| .sumElimR (V := VE') toF'
| .inr FIsValue =>
let VF j : Value := if h : j < n then
⟨F j, FIsValue j ⟨Nat.zero_le _, h, Nat.mod_one _⟩⟩
else
default
rw [Range.map_eq_of_eq_of_mem'' (fun i mem => by
show F i = (VF i).val
dsimp only [VF]
rw [dif_pos mem.upper]
)]
exact .inl ⟨_, .sumElimIntro mem⟩
· case equiv ih => exact ih rfl
namespace Typing
open Environment TermVarInEnvironment in
theorem weakening_r' (EtyT: [[ Δ, Δ'' ⊢ E: T ]]) (wf: [[ ⊢ Δ, Δ', Δ'' ]]): [[ Δ, Δ', Δ'' ⊢ E: T ]] := by
generalize Δ_eq : [[ (Δ, Δ'') ]] = Δ_ at EtyT
induction EtyT generalizing Δ''
case var Δ_ x T wf' xin =>
subst Δ_
refine .var wf ?_
clear wf'
induction Δ' generalizing Δ''
. case empty => simp_all [empty_append]
. case typeExt Δ' a K ih =>
rw [<- append_type_assoc]
apply ih
. simp_all [append_type_assoc]
. apply append_elim at xin
cases xin
. case inl xin =>
apply TermVarInEnvironment.weakening_r
. simp_all [TermVarNotInDom, TermVarInDom, termVarDom_append, termVarDom]
. simp_all
. case inr xin =>
simp_all [TermVarInEnvironment.weakening_l]
. case termExt _ Δ' x' T' ih =>
rw [<- append_term_assoc]
apply ih
. simp_all [append_term_assoc]
. rw [append_term_assoc]
apply TermVarInEnvironment.append_elim at xin
cases xin
. case inl xin =>
apply TermVarInEnvironment.weakening_r
. simp_all
. by_cases (x = x')
. case pos eq =>
subst x'
rw [<- append_term_assoc, append_assoc] at wf
have xinfv := wf.append_termVar_fresh_l x (by simp_all [termVarDom_append, termVarDom])
rw [termVarDom_append] at xinfv
aesop (add norm TermVarNotInDom, norm TermVarInDom, safe forward TermVarInDom_of)
. case neg neq =>
constructor <;> simp_all [TermVarNe]
. case inr xin =>
simp_all [TermVarInEnvironment.weakening_l]
case lam Δ_ A E T I EtyT ih =>
subst Δ_
refine .lam (I := I ++ Δ.termVarDom ++ Δ'.termVarDom ++ Δ''.termVarDom) (λ x xnin => ?_)
rw [append_termExt_assoc, append_termExt_assoc]
refine ih x (by simp_all) ?_ (by rw [append_termExt_assoc])
-- wts. ⊢ Δ, Δ', Δ'', x: A
refine .termVarExt wf (by simp_all [TermVarNotInDom, TermVarInDom, termVarDom_append]) ?_
-- wts. Δ, Δ', Δ'' ⊢ A: *
have := EtyT x (by simp_all)
have := this.WellFormedness_of
cases this; case termVarExt h1 h2 AkiStar =>
refine AkiStar.weakening_r' (λ a anin => ?_)
exact wf.append_typeVar_fresh_l a (by simp_all [typeVarDom_append])
case typeLam Δ_ A E T I EtyT ih =>
subst Δ_
refine .typeLam (I := I ++ Δ.typeVarDom ++ Δ'.typeVarDom ++ Δ''.typeVarDom) (λ a anin => ?_)
rw [append_typeExt_assoc, append_typeExt_assoc]
refine ih a (by simp_all) ?_ (by rw [append_typeExt_assoc])
exact .typeVarExt wf (by simp_all [TypeVarNotInDom, TypeVarInDom, typeVarDom_append])
case typeApp Δ_ E K T B EtyT BkiK ih =>
subst Δ_
refine .typeApp (ih wf rfl) ?_
apply BkiK.weakening_r' (λ a anin => ?_)
exact wf.append_typeVar_fresh_l a (by simp_all [typeVarDom_append])
case sumIntro i n Δ_ _ T _ mem ty TkiStar h ih =>
subst Δ_
refine .sumIntro mem (ty.weakening wf) (λ x xin => ?_) h
specialize TkiStar x xin
refine TkiStar.weakening_r' (λ a anin => ?_)
exact wf.append_typeVar_fresh_l a (by simp_all [typeVarDom_append])
case sumElim Δ_ E n T _ F B EtyT FtyTB BkiStar ih1 ih2 =>
subst Δ_
refine .sumElim (ih1 wf rfl) (λ x xin => ih2 x xin wf rfl) ?_
apply BkiStar.weakening_r' (λ a anin => ?_)
exact wf.append_typeVar_fresh_l a (by simp_all [typeVarDom_append])
case equiv Δ_ E T T' EtyT equiv ih =>
subst Δ_
refine .equiv (ih wf rfl) (equiv.weakening wf.EnvironmentTypeWellFormedness_of)
all_goals aesop (add unsafe constructors Typing) (config := { enableSimp := false })
theorem weakening_r (EtyT: [[ Δ ⊢ E: T ]]) (wf: [[ ⊢ Δ, Δ' ]]): [[ Δ, Δ' ⊢ E: T ]] := by
apply weakening_r' (Δ'' := Environment.empty) <;> simp_all [Environment.append]
theorem term_subst' (EtyA: [[ Δ, x: T, Δ' ⊢ E: A ]]) (FtyT : [[ Δ ⊢ F: T ]]): [[ Δ, Δ' ⊢ E[F/x] : A ]] := by
generalize Δ_eq : [[ (Δ, x:T, Δ') ]] = Δ_ at EtyA
induction EtyA generalizing Δ' <;> try simp_all [Term.TermVar_subst]
. case var Δ_ x' A wf x'in =>
subst Δ_
by_cases (x = x')
. case pos eq =>
simp_all
subst x'
-- 1. by wf we know x ∉ Δ'.typeVarDom
have fresh := wf.append_termVar_fresh_r x (by constructor)
-- 2. then by uniqueness we know from x'In that A = T
have eq := x'in.unique (T':=T) (by
apply TermVarInEnvironment.weakening_r fresh
constructor
)
subst A
-- 3. then wts Δ, Δ' ⊢ F: T, by weakening FtyT we are done
apply weakening_r FtyT wf.TermVar_drop
. case neg neq =>
simp_all
-- 1. by x'in we know x': A is either in (Δ, x: T) or Δ'
apply TermVarInEnvironment.append_elim at x'in
refine .var wf.TermVar_drop ?_
cases x'in
. case inl x'in =>
-- 2a. If x': A ∈ Δ, x: T, we also know that x': A ∉ dom(Δ')
obtain ⟨notInΔ', x'in⟩ := x'in
-- 3a. and by x ≠ x' we know x': A ∈ Δ.
-- wts. x': A ∈ Δ, Δ', by weakening we are done
exact TermVarInEnvironment.weakening_r notInΔ' (by cases x'in <;> simp_all)
. case inr x'in =>
-- 2b. If x': A ∈ Δ', similarly by weakening we are done
exact TermVarInEnvironment.weakening_l x'in
. case lam Δ_ A E B I EtyB ih =>
subst Δ_
refine .lam (I := x :: I) (λ x' x'nin => ?_)
rw [<- FtyT.TermVarLocallyClosed_of.TermVar_open_TermVar_subst_comm (by aesop)]
exact ih x' (by simp_all) (by rw [Environment.append_termExt_assoc])
. case app Δ_ E1 A B E2 E1tyAB E2tyA ih1 ih2 =>
subst Δ_
exact .app (ih1 rfl) (ih2 rfl)
. case typeLam Δ_ K E A I EtyA ih =>
subst Δ_
refine .typeLam (I := x :: (I ++ F.freeTypeVars)) (λ a' a'nin => ?_)
rw [<- FtyT.TermTypeVarLocallyClosed_of.TermVar_open_TypeVar_subst_comm]
exact ih a' (by simp_all) (by rw [Environment.append_typeExt_assoc])
. case typeApp Δ_ E K A B EtyA BkiK ih =>
subst Δ_
exact .typeApp (ih rfl) BkiK.TermVar_drop
. case prodIntro Δ_ _ _ _ _ wf _ h ih =>
subst Δ_
exact .prodIntro wf.TermVar_drop (ih · · rfl) h
. case prodElim Δ_ _ n _ _ _ _ _ ih =>
subst Δ_
exact .prodElim (n := n) (ih rfl) (by simp_all)
. case sumIntro _ n Δ_ _ _ _ mem EtyA AkiStar h ih =>
subst Δ_
exact .sumIntro (n := n) mem (ih rfl) (λ x xin => AkiStar x xin |>.TermVar_drop) h
. case sumElim Δ_ _ n _ _ _ _ _ _ BkiStar ih1 ih2 =>
subst Δ_
exact .sumElim (n := n) (ih1 rfl) (λ x xin => ih2 x xin rfl) BkiStar.TermVar_drop
. case equiv Δ_ E A B EtyA equiv ih =>
subst Δ_
exact .equiv (ih rfl) equiv.TermVar_drop
theorem term_subst (EtyA: [[ Δ, x: T ⊢ E: A ]]) (FtyT : [[ Δ ⊢ F: T ]]): [[ Δ ⊢ E[F/x] : A ]] :=
Typing.term_subst' (Δ' := [[(ε)]]) EtyA FtyT
theorem Term_open (EtyA : Typing [[(Δ, x : B, Δ')]] (.TermVar_open E x n) A)
(xnin : x ∉ E.freeTermVars) (FtyB : [[Δ ⊢ F : B]]) : Typing [[(Δ, Δ')]] (.Term_open E F n) A := by
rw [← Term.TermVar_open_TermVar_subst_eq_Term_open_of_not_mem_freeTermVars xnin]
exact EtyA.term_subst' FtyB
theorem Term_multi_open (EtyA : [[Δ,,, </ x@i : B@i // i in [:n] />, Δ' ⊢ E^^^x#n : A]])
(xninE : ∀ i, x i ∉ E.freeTermVars) (xninF : ∀ i, ∀ j ∈ [:n], x i ∉ (F j).freeTermVars)
(xinj : x.Injective') (FtyB : ∀ i ∈ [:n], [[Δ ⊢ F@i : B@i]])
: [[Δ, Δ' ⊢ E^^^^F@@i#n/x : A]] := by match n with
| 0 =>
rw [Range.map_same_eq_nil, Environment.multiTermExt, Term.TermVar_multi_open] at EtyA
exact EtyA
| n' + 1 =>
rw [Term.Term_multi_open]
let mem : n' ∈ [:n'+1] := ⟨Nat.zero_le _, Nat.le.refl, Nat.mod_one _⟩
apply Term_multi_open _ (Term.not_mem_freeTermVars_Term_open_intro (xninE _) <| xninF · _ mem)
(by
intro i j mem
exact xninF i _ ⟨Nat.zero_le _, Nat.lt_add_right _ mem.upper, Nat.mod_one _⟩
) xinj (FtyB · ⟨Nat.zero_le _, Nat.lt_add_right _ ·.upper, Nat.mod_one _⟩)
rw [Range.map_eq_snoc_of_lt (Nat.zero_lt_succ _), Environment.multiTermExt_snoc,
Nat.succ_sub_one, Term.TermVar_multi_open, Term.TermVar_multi_open_comm Nat.le.refl] at EtyA
rw [Term.Term_open_TermVar_multi_open_comm (FtyB _ mem |>.TermVarLocallyClosed_of) Nat.le.refl]
let Δxwf := EtyA.WellFormedness_of.weakening.TermVar_drop (Δ' := .empty)
apply EtyA.Term_open
· apply Term.not_mem_freeTermVars_TermVar_multi_open_intro <| xninE n'
intro i lt eq
exact Nat.ne_of_lt lt <| xinj _ _ eq.symm
· rw [← Environment.append_empty (Δ := .multiTermExt ..),
Environment.multiTermExt_eq_append (Δ' := .empty), Environment.append_empty] at Δxwf ⊢
exact FtyB _ mem |>.weakening Δxwf (Δ'' := .empty)
open Environment TermVarInEnvironment in
theorem type_subst' (EtyA: [[ Δ, a: K, Δ' ⊢ E: A ]]) (BkiK : [[ Δ ⊢ B: K ]]): [[ Δ, Δ'[B/a] ⊢ E[B/a] : A[B/a] ]] := by
generalize Δ_eq : [[ (Δ, a:K, Δ') ]] = Δ_ at EtyA
induction EtyA generalizing Δ' <;> try simp_all [Term.TypeVar_subst, Type.TypeVar_subst]
. case var Δ_ x' A wf x'in =>
subst Δ_
refine .var (wf.TypeVar_subst BkiK) ?_
obtain ⟨x'nin, x'in'⟩ | x'in' := x'in.append_elim
. case inl.intro =>
-- a) x': A ∈ Δ, wts. x': A[B/α] ∈ Δ
refine append_intro_l ?_ (by
clear * - x'nin
simp_all [TermVarNotInDom, TermVarInDom]
induction Δ' <;> simp_all [TypeVar_subst, termVarDom]
)
-- 1. by wf we know ∀x: A ∈ Δ, a ∉ A.freeTypeVars
cases x'in'; case typeVarExt x'in' =>
rw [<- append_type_assoc] at wf
have anin := x'in'.freeTypeVars_in_Δ wf.weakening a
|>.mt (wf.append_typeVar_fresh_l a (by simp_all [typeVarDom_append, typeVarDom]))
-- 2. so a ∉ A, therefore A[B/a] = A, so x': A[B/α] ∈ Δ. Done.
rw [Type.TypeVar_subst_id_of_not_mem_freeTypeVars anin]
exact x'in'
. case inr =>
-- b) x': A ∈ Δ', by definition of Env.TypeVar_subst and Kind.TypeVar_subst we are done.
clear * - x'in'
induction x'in' <;> simp_all [TypeVar_subst] <;> constructor <;> simp_all
. case lam Δ_ A1 E A2 I EtyA2 ih =>
subst Δ_
refine .lam (I := I ++ Δ.termVarDom ++ Δ'.termVarDom) (λ x xnin => ?_)
rw [<- Term.TypeVar_open_TermVar_subst_comm]
exact ih x (by simp_all) (by rw [append_termExt_assoc])
. case app Δ_ E1 A B E2 E1tyAB E2tyA ih1 ih2 =>
subst Δ_
exact .app (ih1 rfl) (ih2 rfl)
. case typeLam Δ_ K' E A I EtyA ih =>
subst Δ_
refine .typeLam (I := a :: I ++ Δ.typeVarDom ++ Δ'.typeVarDom) (λ a' a'nin => ?_)
rw [
<- BkiK.TypeVarLocallyClosed_of.Term_TypeVar_open_TypeVar_subst_comm (by aesop),
<- BkiK.TypeVarLocallyClosed_of.TypeVar_open_TypeVar_subst_comm (by aesop)
]
exact ih a' (by simp_all) (by rw [append_typeExt_assoc])
. case typeApp Δ_ E K2 A1 A2 EtyA1 A2kiK2 ih =>
subst Δ_
rw [BkiK.TypeVarLocallyClosed_of.Type_open_TypeVar_subst_dist]
refine .typeApp (ih rfl) ?_
exact A2kiK2.subst' EtyA1.WellFormedness_of BkiK
. case prodIntro Δ_ _ _ _ _ wf _ h _ =>
subst Δ_
refine .prodIntro (wf.subst BkiK) (by simp_all) h
. case prodElim Δ_ E n A _ i EtyA iRange ih =>
subst Δ_
specialize ih rfl
rw [Range.map_eq_of_eq_of_mem (fun _ _ => Function.comp.eq_def ..)] at ih
have ⟨A', A'eq⟩: ∃A': ℕ → «Type», ∀i, A' i = (A i).TypeVar_subst a B := ⟨λi => (A i).TypeVar_subst a B, λi => by simp⟩
rw [<- A'eq i]; rw [<- funext (λi => A'eq i)] at ih
refine .prodElim (n := n) ih iRange
. case sumIntro _ n Δ_ _ _ _ _ EtyA A'kiStar h _ =>
subst Δ_
refine .sumIntro (n := n) (by simp_all) (by simp_all) (λ x xin => ?_) h
exact A'kiStar x xin |>.subst' EtyA.WellFormedness_of BkiK
. case sumElim Δ_ E n _ _ _ _ EtyA _ B'kiStar ih1 ih2 =>
subst Δ_
exact .sumElim (n := n) (ih1 rfl) (λ x xin => ih2 x xin rfl) (B'kiStar.subst' EtyA.WellFormedness_of BkiK)
. case equiv Δ_ E A A' EtyA equiv ih =>
subst Δ_
refine .equiv (ih rfl) (equiv.subst' EtyA.TypeVarLocallyClosed_of EtyA.WellFormedness_of BkiK)
theorem type_subst (EtyA: [[ Δ, a: K ⊢ E: A ]]) (BkiK : [[ Δ ⊢ B: K ]]): [[ Δ ⊢ E[B/a] : A[B/a] ]] :=
Typing.type_subst' (Δ' := [[(ε)]]) EtyA BkiK
theorem Type_open
(EtyA : Typing [[(Δ, a : K, Δ')]] (.TypeVar_open E a n) (.TypeVar_open A a n))
(aninE : a ∉ E.freeTypeVars) (aninA : a ∉ A.freeTypeVars) (Bki : [[Δ ⊢ B : K]])
: Typing [[(Δ, Δ' [B / a])]] (.Type_open E B n) (.Type_open A B n) := by
rw [← Term.TypeVar_open_TypeVar_subst_eq_Type_open_of_not_mem_freeTypeVars aninE,
← Type.TypeVar_open_TypeVar_subst_eq_Type_open_of_not_mem_freeTypeVars aninA]
exact EtyA.type_subst' Bki
theorem Type_open_Type_open
(EtyA : Typing [[(Δ, a : K, Δ')]] (.TypeVar_open E a m) (.Type_open A (.TypeVar_open B a n) l))
(aninE : a ∉ E.freeTypeVars) (aninA : a ∉ A.freeTypeVars) (aninB : a ∉ B.freeTypeVars)
(B'ki : [[Δ ⊢ B' : K]])
: Typing [[(Δ, Δ' [B' / a])]] (.Type_open E B' m) (.Type_open A (.Type_open B B' n) l) := by
let B'lc := B'ki.TypeVarLocallyClosed_of.weaken (n := l)
rw [Nat.zero_add] at B'lc
rw [← Term.TypeVar_open_TypeVar_subst_eq_Type_open_of_not_mem_freeTypeVars aninE,
← Type.TypeVar_open_TypeVar_subst_eq_Type_open_of_not_mem_freeTypeVars aninB,
← Type.TypeVar_subst_id_of_not_mem_freeTypeVars aninA, ← B'lc.Type_open_TypeVar_subst_dist]
exact EtyA.type_subst' B'ki
theorem Type_open_Type_multi_open
(EtyA : [[Δ,, </ a@i : K@i // i in [:n] />, Δ' ⊢ E^^^a#n : A^^(B^^^a#n)]])
(aninE : ∀ i, a i ∉ E.freeTypeVars) (aninA : ∀ i, a i ∉ A.freeTypeVars)
(aninB : ∀ i, a i ∉ B.freeTypeVars)
(aninB' : ∀ i, ∀ j ∈ [:n], a i ∉ (B' j).freeTypeVars) (ainj : a.Injective')
(B'ki : ∀ i ∈ [:n], [[Δ ⊢ B'@i : K@i]])
: [[Δ, (Δ' ! </ [B'@i / a@i] // i in [:n] />) ⊢ E^^^^B'@@i#n/a : A^^(B^^^^B'@@i#n/a)]] := by
match n with
| 0 =>
rw [Range.map_same_eq_nil, Environment.TypeVar_multi_subst]
rw [Range.map_same_eq_nil, Environment.multiTypeExt, Term.TypeVar_multi_open,
Type.TypeVar_multi_open] at EtyA
exact EtyA
| n' + 1 =>
rw [Range.map_eq_snoc_of_lt (Nat.zero_lt_succ _), Environment.TypeVar_multi_subst_snoc,
Nat.succ_sub_one, Term.Type_multi_open, Type.Type_multi_open]
let mem : n' ∈ [:n'+1] := ⟨Nat.zero_le _, Nat.le.refl, Nat.mod_one _⟩
apply Type_open_Type_multi_open _
(Term.not_mem_freeTypeVars_Type_open_intro (aninE _) <| aninB' · _ mem) aninA
(Type.not_mem_freeTypeVars_Type_open_intro (aninB _) <| aninB' · _ mem)
(aninB' · · ⟨Nat.zero_le _, Nat.lt_add_right _ ·.upper, Nat.mod_one _⟩) ainj
(B'ki · ⟨Nat.zero_le _, Nat.lt_add_right _ ·.upper, Nat.mod_one _⟩)
rw [Range.map_eq_snoc_of_lt (Nat.zero_lt_succ _), Environment.multiTypeExt_snoc,
Nat.succ_sub_one, Term.TypeVar_multi_open, Term.TypeVar_multi_open_comm Nat.le.refl,
Type.TypeVar_multi_open, Type.TypeVar_open_TypeVar_multi_open_comm Nat.le.refl] at EtyA
let Blc := B'ki _ mem |>.TypeVarLocallyClosed_of
rw [Term.Type_open_TypeVar_multi_open_comm Blc Nat.le.refl,
Blc.Type_open_TypeVar_multi_open_comm Nat.le.refl]
let .typeVarExt Δawf .. := EtyA.WellFormedness_of.weakening
apply EtyA.Type_open_Type_open
(Term.not_mem_freeTypeVars_TypeVar_multi_open_intro (aninE _)
fun _ lt eq => Nat.ne_of_lt lt <| ainj _ _ eq.symm) (aninA _)
(Type.not_mem_freeTypeVars_TypeVar_multi_open_intro (aninB _)
fun _ lt eq => Nat.ne_of_lt lt <| ainj _ _ eq.symm)
specialize B'ki _ mem
rw [← Environment.append_empty (Δ := .multiTypeExt ..),
Environment.multiTypeExt_eq_append (Δ' := .empty)] at Δawf ⊢
exact B'ki.weakening Δawf (Δ'' := .empty)
end Typing
theorem preservation.sandwich {α: Type} {nl nr : ℕ} {F1 F3: ℕ → α} {F2: α}:
let G i := if i < nl then F1 i else if i = nl then F2 else F3 (i - nl - 1)
[0:nl].map (λi => F1 i) ++ F2 :: [0:nr].map (λi => F3 i) = [0:nl + 1 + nr].map G := by
intro G
rw [progress.sandwich (n := nl + 1 + nr) (i := nl) (by omega)]
simp_all
refine List.append_eq_append ?_ ?_
. exact Std.Range.map_eq_of_eq_of_mem (λ i iltnl => by simp_all [Membership.mem])
. refine List.cons_eq_cons.mpr ⟨rfl, ?_⟩
refine Std.Range.map_eq_of_eq_of_mem (λ i iltnl => ?_)
repeat' rw [if_neg (by omega)]
exact congrArg _ (by omega)
local instance : Inhabited Term where
default := .prodIntro []
theorem preservation (EtyA: [[Δ ⊢ E : A]]) (EE': [[E -> E']]): [[Δ ⊢ E' : A]] := by
induction EtyA generalizing E' <;> (try cases EE'; done) -- values can't step
. case app Δ E A B F EtyAarrB FtyA ihE ihF =>
cases EE'
. case appL E' EE' => exact .app (ihE EE') FtyA
. case appR F' E FF' => exact .app EtyAarrB (ihF FF')
. case lamApp A' E F =>
have ⟨eqA'A, I, EtyAarrB⟩ := EtyAarrB.inv_arr
have ⟨x, notIn⟩ := (I ++ E.freeTermVars).exists_fresh
rw [<- Term.TermVar_subst_intro_of_not_mem_freeTermVars (a := x) (by simp_all)]
exact EtyAarrB x (by simp_all) |>.term_subst (.equiv FtyA eqA'A.symm)
. case typeApp Δ E K A B EtyA BkiK ih =>
cases EE'
. case typeApp E' EE' => exact .typeApp (ih EE') BkiK
. case typeLamApp K' E =>
have ⟨Keq, I, EtyA⟩ := EtyA.inv_forall
subst K'
have ⟨a, notIn⟩ := (I ++ E.freeTypeVars ++ A.freeTypeVars).exists_fresh
specialize EtyA a (by simp_all)
rw [<- Term.TypeVar_subst_intro_of_not_mem_freeTypeVars (a := a) (by simp_all)]
rw [<- Type.TypeVar_subst_intro_of_not_mem_freeTypeVars (a := a) (by simp_all)]
exact EtyA.type_subst BkiK
. case prodIntro Δ n E A _ wf EtyA h ih =>
generalize eqE_: Term.prodIntro ([0:n].map (λi => E i)) = E_ at EE'
cases EE' <;> try cases eqE_
. case prodIntro E_ E' nl V nr Er EE' =>
injection eqE_ with eq
have llt : nl < n := by
have := congrArg List.length eq
simp [List.length_append, List.length_cons, List.length_map, Std.Range.length_toList] at this
omega
rw [progress.sandwich llt] at eq
have ⟨eql, eqr⟩ := List.append_inj eq (by simp_all [Std.Range.length_toList]); clear eq
have eqEV := Std.Range.eq_of_mem_of_map_eq eql; clear eql
injection eqr with eqEE_ eqr; simp at eqr; subst eqEE_
have := Std.Range.length_eq_of_mem_eq eqr; subst this
have eqEEr_shift := Std.Range.eq_of_mem_of_map_eq eqr; clear eqr
rw [preservation.sandwich]
simp_all; rwomega nl + 1 + (n - (nl + 1)) = n
refine .prodIntro wf (λ i iltn => ?_) h
repeat' split
. case _ iltnl =>
rw [← eqEV i (by simp_all [Membership.mem])]
exact EtyA i (by simp_all [Membership.mem])
. case _ igenl ieqnl =>
subst i
exact ih nl (by simp_all) EE'
. case _ igenl inenl =>
rw [← eqEEr_shift _ (by simp_all [Membership.mem]; omega)]
rwomega i - nl - 1 + (nl + 1) = i
exact EtyA i (by simp_all [Membership.mem])
. case prodElim Δ E n A i EtyA iltn ih =>
cases EE'
. case prodElim E' EE' => exact .prodElim (ih EE') iltn
. case prodElimIntro n' E iltn' =>
clear ih
have ⟨eqn'n, EtyA⟩ := EtyA.inv_prod
simp_all [NatInZeroRange]
. case sumIntro i n Δ E A ilen EtyA AkiStar ih => cases EE'; constructor <;> simp_all
. case sumElim Δ E n A _ F B EtyA FtyAB BkiStar ih1 ih2 =>
generalize eqEF: [[ case E {</ F@i // i in [:n] />} ]] = EF at EE'
cases EE' <;> try cases eqEF
. case sumElimL E_ E' n_ F_ EE' =>
injection eqEF with eqEE_ eq; subst E_
have eqnn_ := Std.Range.length_eq_of_mem_eq eq; subst eqnn_
have eqFF_ := Std.Range.eq_of_mem_of_map_eq eq; clear eq
refine .sumElim (ih1 EE') (λ x xin => by simp_all) BkiStar
. case sumElimR F_ F' V nl V' nr Fr FF' =>
simp_all
obtain ⟨eqEV, eq⟩ := eqEF; subst E
let G i := if i < nl then (V' i).val else if i = nl then F_ else Fr (i - nl - 1)
let G' i := if i < nl then (V' i).val else if i = nl then F' else Fr (i - nl - 1)
have Geq : [0:nl].map (λ i => (V' i).val) ++ F_ :: [0:nr].map (λ j => Fr j) = [0:nl + 1 + nr].map G := preservation.sandwich
rw [Geq] at eq
have G'eq : [0:nl].map (λ i => (V' i).val) ++ F' :: [0:nr].map (λ j => Fr j) = [0:nl + 1 + nr].map G' := preservation.sandwich
rw [G'eq]
have eqn := Std.Range.length_eq_of_mem_eq eq; subst eqn
have : F nl = F_ := by
clear * - Geq eq
have eqFG : F nl = G nl := by
clear * - eq
have := congrArg (λ i => i.get! nl) eq
simp only at this
rw [
Std.Range.get!_map (by omega),
Std.Range.get!_map (by omega)] at this
exact this
clear eq
have := congrArg (λ i => i.get! nl) Geq
simp only at this
rw [Std.Range.get!_map (by omega)] at this
rw [List.get!_eq_getD, List.getD_eq_getElem?_getD, List.getElem?_append,
if_neg (by simp_all [Std.Range.length_toList]), List.length_map, Std.Range.length_toList] at this
simp_all
subst F_
have F'tyAB := ih2 nl (by simp_all [Membership.mem]; omega) FF'
refine .sumElim EtyA (λ i iltn => ?_) BkiStar
simp_all
split
. case isTrue iltnl =>
have eqFG := eq i (Std.Range.mem_toList_of_mem (by simp_all [Membership.mem]))
specialize FtyAB i (by simp_all [Membership.mem])
rw [eqFG] at FtyAB
unfold G at FtyAB
simp_all
. case isFalse igenl =>
split
. case isTrue ieqnl =>
subst i
exact ih2 nl (by simp_all) FF'
. case isFalse inenl =>
have eqFG := eq i (Std.Range.mem_toList_of_mem (by simp_all [Membership.mem]))
specialize FtyAB i (by simp_all [Membership.mem])
rw [eqFG] at FtyAB
unfold G at FtyAB
rw [← ite_not] at FtyAB
simp_all
. case sumElimIntro i n_ V V' iltn_ =>
injection eqEF with eqEV eq; subst E
have eqnn_ := Std.Range.length_eq_of_mem_eq eq; subst eqnn_
have eqFV' := Std.Range.eq_of_mem_of_map_eq eq; clear eq
have ⟨_, VtyA, _⟩ := EtyA.inv_sum
refine .app (by simp_all) VtyA
. case equiv Δ E A B EtyA eq ih => exact .equiv (ih EE') eq
end TabularTypes.«F⊗⊕ω»