-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathSubstitution.lean
202 lines (159 loc) · 9.19 KB
/
Substitution.lean
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
-- https://plfa.github.io/Substitution/#plfa_plfa-part2-Substitution-2341
import Plfl.Init
import Plfl.Untyped
namespace Substitution
open Untyped Notation
abbrev Rename (Γ Δ) := ∀ {a : Ty}, Γ ∋ a → Δ ∋ a
abbrev Subst (Γ Δ) := ∀ {a : Ty}, Γ ∋ a → Δ ⊢ a
-- https://plfa.github.io/Substitution/#the-%CF%83-algebra-of-substitution
abbrev ids : Subst Γ Γ := .var
abbrev shift : Subst Γ (Γ‚ a) := .var ∘ .s
abbrev cons (m : Δ ⊢ a) (σ : Subst Γ Δ) : Subst (Γ‚ a) Δ
| _, .z => m
| _, .s x => σ x
abbrev seq (σ : Subst Γ Δ) (τ : Subst Δ Φ) : Subst Γ Φ := ⟪τ⟫ ∘ σ
namespace Notation
scoped infixr:60 " ⦂⦂ " => cons
scoped infixr:50 " ⨟ " => seq
end Notation
open Notation
open Subst
-- https://plfa.github.io/Substitution/#relating-the-σ-algebra-and-substitution-functions
def ren (ρ : Rename Γ Δ) : Subst Γ Δ := ids ∘ ρ
section
variable {m : Δ ⊢ a} {σ : Subst Γ Δ} {τ : Subst Δ Φ}
-- https://plfa.github.io/Substitution/#proofs-of-sub-head-sub-tail-sub-η-z-shift-sub-idl-sub-dist-and-sub-app
@[simp] theorem sub_head : ⟪m ⦂⦂ σ⟫ (`.z) = m := rfl
@[simp] theorem sub_tail : (shift ⨟ m ⦂⦂ σ) = σ (a := b) := rfl
@[simp] theorem sub_η {σ : Subst (Γ‚ a) Δ} : (⟪σ⟫ (`.z) ⦂⦂ (shift ⨟ σ)) = σ (a := b) := by ext i; cases i <;> rfl
@[simp] theorem z_shift : ((`.z) ⦂⦂ shift) = @ids (Γ‚ a) b := by ext i; cases i <;> rfl
@[simp] theorem ids_seq : (ids ⨟ σ) = σ (a := a) := rfl
@[simp] theorem sub_ap {l m : Γ ⊢ ✶} : ⟪σ⟫ (l □ m) = (⟪σ⟫ l) □ (⟪σ⟫ m) := rfl
@[simp] theorem sub_dist : @Eq (Γ‚ a ∋ b → Φ ⊢ b) ((m ⦂⦂ σ) ⨟ τ) ((⟪τ⟫ m) ⦂⦂ (σ ⨟ τ)) := by ext i; cases i <;> rfl
end
-- https://plfa.github.io/Substitution/#interlude-congruences
/-
Nothing to do.
-/
section
variable {m : Γ ⊢ a} {σ : Subst Γ Δ} {ρ : Rename Γ Δ}
-- https://plfa.github.io/Substitution/#relating-rename-exts-ext-and-subst-zero-to-the-%CF%83-algebra
@[simp] theorem ren_ext : @Eq (Γ‚ b ∋ c → Δ‚ b ⊢ c) (ren (ext ρ)) (exts (ren ρ)) := by ext i; cases i <;> rfl
@[simp] theorem ren_shift : @Eq (Γ ∋ a → Γ‚ b ⊢ a) (ren .s) shift := by congr
theorem rename_subst_ren {Γ Δ} {ρ : Rename Γ Δ} {m : Γ ⊢ a} : rename ρ m = ⟪ren ρ⟫ m := by
match m with
| ` _ => rfl
| ƛ n => apply congr_arg Term.lam; rw [rename_subst_ren]; congr; funext _; exact ren_ext
| l □ m => simp only [sub_ap]; apply congr_arg₂ Term.ap <;> exact rename_subst_ren
theorem rename_shift : @Eq (Γ‚ ✶ ⊢ a) (rename .s m) (⟪shift⟫ m) := by
simp only [rename_subst_ren]; congr
theorem exts_cons_shift : exts (a := a) (b := b) σ = (`.z ⦂⦂ (σ ⨟ shift)) := by
ext i; cases i <;> simp only [exts, rename_subst_ren, ren_shift]; rfl
theorem ext_cons_z_shift : @Eq (Γ‚ b ∋ a → Δ‚ b ⊢ a) (ren (ext ρ)) (`.z ⦂⦂ (ren ρ ⨟ shift)) := by
ext i; cases i <;> simp only [ren_ext, exts, rename_subst_ren, ren_shift]; rfl
theorem subst_z_cons_ids {m : Γ ⊢ a} : @Eq (Γ‚ ✶ ∋ a → Γ ⊢ a) (subst₁σ m) (m ⦂⦂ ids) := by
ext i; cases i <;> rfl
-- https://plfa.github.io/Substitution/#proofs-of-sub-abs-sub-id-and-rename-id
theorem sub_lam {σ : Subst Γ Δ} {n : Γ‚ ✶ ⊢ ✶} : ⟪σ⟫ (ƛ n) = (ƛ ⟪(`.z) ⦂⦂ (σ ⨟ shift)⟫ n) := by
change (ƛ ⟪exts σ⟫ n) = _; congr; funext _; exact exts_cons_shift
@[simp] theorem exts_ids : @Eq (Γ‚ b ∋ a → _) (exts ids) ids := by ext i; cases i <;> rfl
theorem sub_ids {Γ} {m : Γ ⊢ a} : ⟪ids (Γ := Γ)⟫ m = m := by
match m with
| ` _ => rfl
| ƛ n => apply congr_arg Term.lam; convert sub_ids; exact exts_ids
| l □ m => simp only [sub_ap]; apply congr_arg₂ Term.ap <;> exact sub_ids
theorem rename_id : rename (λ {a} x => x) m = m := by
convert sub_ids; ext; simp only [rename_subst_ren, ren]; congr
-- https://plfa.github.io/Substitution/#proof-of-sub-idr
theorem seq_ids : @Eq (Γ ∋ a → Δ ⊢ a) (σ ⨟ ids) σ := by
ext; simp only [Function.comp_apply, sub_ids]
end
section
variable {m : Γ ⊢ a} {ρ : Rename Δ Φ} {ρ' : Rename Γ Δ}
-- https://plfa.github.io/Substitution/#proof-of-sub-sub
@[simp] theorem comp_ext : @Eq (Γ‚ b ∋ a → _) ((ext ρ) ∘ (ext ρ')) (ext (ρ ∘ ρ')) := by
ext i; cases i <;> rfl
theorem comp_rename {Γ Δ Φ} {m : Γ ⊢ a} {ρ : Rename Δ Φ} {ρ' : Rename Γ Δ}
: rename ρ (rename ρ' m) = rename (ρ ∘ ρ') m := by
match m with
| ` _ => rfl
| ƛ n => apply congr_arg Term.lam; convert comp_rename; exact comp_ext.symm
| l □ m => apply congr_arg₂ Term.ap <;> exact comp_rename
theorem comm_subst_rename {Γ Δ} {σ : Subst Γ Δ} {ρ : ∀ {Γ}, Rename Γ (Γ‚ ✶)}
(r : ∀ {x : Γ ∋ ✶}, exts σ (ρ x) = rename ρ (σ x)) {m : Γ ⊢ ✶}
: ⟪exts (b := ✶) σ⟫ (rename ρ m) = rename ρ (⟪σ⟫ m)
:= by
match m with
| ` _ => exact r
| l □ m => apply congr_arg₂ Term.ap <;> exact comm_subst_rename r
| ƛ n =>
apply congr_arg Term.lam
let ρ' : ∀ {Γ}, Rename Γ (Γ‚ ✶) := by intro
| [] => intro; intro.
| ✶ :: Γ => intro; exact ext ρ
apply comm_subst_rename (Γ := Γ‚ ✶) (Δ := Δ‚ ✶) (σ := exts σ) (ρ := ρ') (m := n); intro
| .z => rfl
| .s x => calc exts (exts σ) (ρ' (.s x))
_ = rename .s (exts σ (ρ x)) := rfl
_ = rename .s (rename ρ (σ x)) := by rw [r]
_ = rename (.s ∘ ρ) (σ x) := comp_rename
_ = rename (ext ρ ∘ .s) (σ x) := by congr
_ = rename (ext ρ) (rename .s (σ x)) := comp_rename.symm
_ = rename ρ' (exts σ (.s x)) := rfl
end
section
variable {ρ : Rename Γ Δ} {σ : Subst Γ Δ} {τ : Subst Δ Φ} {θ : Subst Φ Ψ}
theorem exts_seq_exts : @Eq (Γ‚ ✶ ∋ a → _) (exts σ ⨟ exts τ) (exts (σ ⨟ τ)) := by
ext i; match i with
| .z => rfl
| .s i => conv_lhs =>
change ⟪exts τ⟫ (rename .s (σ i)); rw [comm_subst_rename (σ := τ) (ρ := .s) rfl]; rfl
theorem sub_sub {Γ Δ Φ} {σ : Subst Γ Δ} {τ : Subst Δ Φ} {m : Γ ⊢ a}
: ⟪τ⟫ (⟪σ⟫ m) = ⟪σ ⨟ τ⟫ m
:= by match m with
| ` _ => rfl
| l □ m => apply congr_arg₂ Term.ap <;> exact sub_sub
| ƛ n => calc ⟪τ⟫ (⟪σ⟫ (ƛ n))
_ = (ƛ ⟪exts τ⟫ (⟪exts σ⟫ n)) := rfl
_ = (ƛ (⟪exts σ ⨟ exts τ⟫ n)) := by apply congr_arg Term.lam; exact sub_sub
_ = (ƛ (⟪exts (σ ⨟ τ)⟫ n)) := by apply congr_arg Term.lam; congr; funext _; exact exts_seq_exts
theorem rename_subst : ⟪τ⟫ (rename ρ m) = ⟪τ ∘ ρ⟫ m := by
simp only [rename_subst_ren, sub_sub]; congr
-- https://plfa.github.io/Substitution/#proof-of-sub-assoc
theorem sub_assoc : @Eq (Γ ∋ a → _) ((σ ⨟ τ) ⨟ θ) (σ ⨟ (τ ⨟ θ)) := by
ext; simp only [Function.comp_apply, sub_sub]
-- https://plfa.github.io/Substitution/#proof-of-subst-zero-exts-cons
theorem subst₁σ_exts_cons {m : Δ ⊢ b} : @Eq (Γ‚ ✶ ∋ a → _) (exts σ ⨟ subst₁σ m) (m ⦂⦂ σ) := by
simp only [
exts_cons_shift, subst_z_cons_ids, sub_dist, sub_head, sub_assoc, sub_tail, seq_ids
]
variable {n : Γ‚ ✶ ⊢ ✶} {m : Γ ⊢ ✶}
-- https://plfa.github.io/Substitution/#proof-of-the-substitution-lemma
theorem subst_comm : (⟪exts σ⟫ n)⟦⟪σ⟫ m⟧ = ⟪σ⟫ (n⟦m⟧) := calc _
_ = ⟪subst₁σ (⟪σ⟫ m)⟫ (⟪exts σ⟫ n) := rfl
_ = ⟪⟪σ⟫ m ⦂⦂ ids⟫ (⟪exts σ⟫ n) := by congr; simp only [subst_z_cons_ids]
_ = ⟪(exts σ) ⨟ ((⟪σ⟫ m) ⦂⦂ ids)⟫ n := sub_sub
_ = ⟪(`.z ⦂⦂ (σ ⨟ shift)) ⨟ (⟪σ⟫ m ⦂⦂ ids)⟫ n := by congr; simp only [exts_cons_shift]
_ = ⟪⟪⟪σ⟫ m ⦂⦂ ids⟫ (`.z) ⦂⦂ ((σ ⨟ shift) ⨟ (⟪σ⟫ m ⦂⦂ ids))⟫ n := by congr; simp only [sub_dist]
_ = ⟪⟪σ⟫ m ⦂⦂ ((σ ⨟ shift) ⨟ (⟪σ⟫ m ⦂⦂ ids))⟫ n := rfl
_ = ⟪⟪σ⟫ m ⦂⦂ (σ ⨟ shift ⨟ ⟪σ⟫ m ⦂⦂ ids)⟫ n := by congr; simp only [sub_assoc]
_ = ⟪⟪σ⟫ m ⦂⦂ (σ ⨟ ids)⟫ n := by congr
_ = ⟪⟪σ⟫ m ⦂⦂ (ids ⨟ σ)⟫ n := by congr; simp only [seq_ids, ids_seq]
_ = ⟪m ⦂⦂ ids ⨟ σ⟫ n := by congr; simp only [sub_dist]
_ = ⟪σ⟫ (⟪m ⦂⦂ ids⟫ n) := sub_sub.symm
_ = ⟪σ⟫ (n⟦m⟧) := by congr; simp only [subst_z_cons_ids]
theorem rename_subst_comm : (rename (ext ρ) n)⟦rename ρ m⟧ = rename ρ (n⟦m⟧) := calc _
_ = (⟪ren (ext ρ)⟫ n)⟦⟪ren ρ⟫ m⟧ := by rw [rename_subst_ren, rename_subst_ren]
_ = (⟪exts (ren ρ)⟫ n)⟦⟪ren ρ⟫ m⟧ := by simp only [ren_ext]
_ = ⟪ren ρ⟫ (n⟦m⟧) := subst_comm
_ = rename ρ (n⟦m⟧) := rename_subst_ren.symm
end
/--
Substitute a term `m` for `♯1` within term `n`.
-/
abbrev subst₁_under₁ (m : Γ ⊢ b) (n : Γ‚ b‚ c ⊢ a) : Γ‚ c ⊢ a := ⟪exts (subst₁σ m)⟫ n
namespace Notation
scoped notation:90 n "⟦" m "⟧₁" => subst₁_under₁ m n
end Notation
theorem substitution {m : Γ‚ ✶‚ ✶ ⊢ ✶} {n : Γ‚ ✶ ⊢ ✶} {l : Γ ⊢ ✶} : m⟦n⟧⟦l⟧ = m⟦l⟧₁⟦n⟦l⟧⟧
:= subst_comm.symm