blob: 8e3e42aa4a10ae98585a9bd7fda94652db93bc44 (
plain)
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
|
module Total.Term
import public Data.SnocList.Elem
import public Thinning
import Syntax.PreorderReasoning
%prefix_record_projections off
infixr 10 ~>
public export
data Ty : Type where
N : Ty
(~>) : Ty -> Ty -> Ty
%name Ty ty
public export
data Term : SnocList Ty -> Ty -> Type where
Var : (i : Elem ty ctx) -> Term ctx ty
Abs : Term (ctx :< ty) ty' -> Term ctx (ty ~> ty')
App : {ty : Ty} -> Term ctx (ty ~> ty') -> Term ctx ty -> Term ctx ty'
Zero : Term ctx N
Suc : Term ctx N -> Term ctx N
Rec : Term ctx N -> Term ctx ty -> Term ctx (ty ~> ty) -> Term ctx ty
%name Term t, u, v
public export
wkn : Term ctx ty -> ctx `Thins` ctx' -> Term ctx' ty
wkn (Var i) thin = Var (index thin i)
wkn (Abs t) thin = Abs (wkn t $ Keep thin)
wkn (App t u) thin = App (wkn t thin) (wkn u thin)
wkn Zero thin = Zero
wkn (Suc t) thin = Suc (wkn t thin)
wkn (Rec t u v) thin = Rec (wkn t thin) (wkn u thin) (wkn v thin)
public export
data Terms : SnocList Ty -> SnocList Ty -> Type where
Base : ctx `Thins` ctx' -> Terms ctx' ctx
(:<) : Terms ctx' ctx -> Term ctx' ty -> Terms ctx' (ctx :< ty)
%name Terms sub
public export
index : Terms ctx' ctx -> Elem ty ctx -> Term ctx' ty
index (Base thin) i = Var (index thin i)
index (sub :< t) Here = t
index (sub :< t) (There i) = index sub i
public export
wknAll : Terms ctx' ctx -> ctx' `Thins` ctx'' -> Terms ctx'' ctx
wknAll (Base thin') thin = Base (thin . thin')
wknAll (sub :< t) thin = wknAll sub thin :< wkn t thin
public export
subst : Len ctx' => Term ctx ty -> Terms ctx' ctx -> Term ctx' ty
subst (Var i) sub = index sub i
subst (Abs t) sub = Abs (subst t $ wknAll sub (Drop id) :< Var Here)
subst (App t u) sub = App (subst t sub) (subst u sub)
subst Zero sub = Zero
subst (Suc t) sub = Suc (subst t sub)
subst (Rec t u v) sub = Rec (subst t sub) (subst u sub) (subst v sub)
public export
restrict : Terms ctx'' ctx' -> ctx `Thins` ctx' -> Terms ctx'' ctx
restrict (Base thin') thin = Base (thin' . thin)
restrict (sub :< t) (Drop thin) = restrict sub thin
restrict (sub :< t) (Keep thin) = restrict sub thin :< t
public export
(.) : Len ctx'' => Terms ctx'' ctx' -> Terms ctx' ctx -> Terms ctx'' ctx
sub2 . (Base thin) = restrict sub2 thin
sub2 . (sub1 :< t) = sub2 . sub1 :< subst t sub2
-- Properties ------------------------------------------------------------------
-- Utilities
cong3 : (0 f : a -> b -> c -> d) -> x1 = x2 -> y1 = y2 -> z1 = z2 -> f x1 y1 z1 = f x2 y2 z2
cong3 f Refl Refl Refl = Refl
-- Weakening
export
wknHomo :
(t : Term ctx ty) ->
(thin1 : ctx `Thins` ctx') ->
(thin2 : ctx' `Thins` ctx'') ->
wkn (wkn t thin1) thin2 = wkn t (thin2 . thin1)
wknHomo (Var i) thin1 thin2 =
cong Var (indexHomo thin2 thin1 i)
wknHomo (Abs t) thin1 thin2 =
cong Abs (wknHomo t (Keep thin1) (Keep thin2))
wknHomo (App t u) thin1 thin2 =
cong2 App (wknHomo t thin1 thin2) (wknHomo u thin1 thin2)
wknHomo Zero thin1 thin2 =
Refl
wknHomo (Suc t) thin1 thin2 =
cong Suc (wknHomo t thin1 thin2)
wknHomo (Rec t u v) thin1 thin2 =
cong3 Rec (wknHomo t thin1 thin2) (wknHomo u thin1 thin2) (wknHomo v thin1 thin2)
export
wknId : Len ctx => (t : Term ctx ty) -> wkn t Thinning.id = t
wknId (Var i) = cong Var (indexId i)
wknId (Abs t) = cong Abs (wknId t)
wknId (App t u) = cong2 App (wknId t) (wknId u)
wknId Zero = Refl
wknId (Suc t) = cong Suc (wknId t)
wknId (Rec t u v) = cong3 Rec (wknId t) (wknId u) (wknId v)
indexWknAll :
(sub : Terms ctx' ctx) ->
(thin : ctx' `Thins` ctx'') ->
(i : Elem ty ctx) ->
index (wknAll sub thin) i = wkn (index sub i) thin
indexWknAll (Base thin') thin i = sym $ cong Var $ indexHomo thin thin' i
indexWknAll (sub :< t) thin Here = Refl
indexWknAll (sub :< t) thin (There i) = indexWknAll sub thin i
wknAllHomo :
(sub : Terms ctx ctx''') ->
(thin1 : ctx `Thins` ctx') ->
(thin2 : ctx' `Thins` ctx'') ->
wknAll (wknAll sub thin1) thin2 = wknAll sub (thin2 . thin1)
wknAllHomo (Base thin) thin1 thin2 = cong Base (assoc thin2 thin1 thin)
wknAllHomo (sub :< t) thin1 thin2 = cong2 (:<) (wknAllHomo sub thin1 thin2) (wknHomo t thin1 thin2)
-- Restrict
indexRestrict :
(thin : ctx `Thins` ctx') ->
(sub : Terms ctx'' ctx') ->
(i : Elem ty ctx) ->
index (restrict sub thin) i = index sub (index thin i)
indexRestrict thin (Base thin') i = sym $ cong Var $ indexHomo thin' thin i
indexRestrict (Drop thin) (sub :< t) i = indexRestrict thin sub i
indexRestrict (Keep thin) (sub :< t) Here = Refl
indexRestrict (Keep thin) (sub :< t) (There i) = indexRestrict thin sub i
restrictId : (len : Len ctx) => (sub : Terms ctx' ctx) -> restrict sub (id @{len}) = sub
restrictId (Base thin) = cong Base (identityRight thin)
restrictId {len = S k} (sub :< t) = cong (:< t) (restrictId sub)
restrictHomo :
(sub : Terms ctx ctx''') ->
(thin1 : ctx'' `Thins` ctx''') ->
(thin2 : ctx' `Thins` ctx'') ->
restrict sub (thin1 . thin2) = restrict (restrict sub thin1) thin2
restrictHomo (Base thin) thin1 thin2 = cong Base (assoc thin thin1 thin2)
restrictHomo (sub :< t) (Drop thin1) thin2 = restrictHomo sub thin1 thin2
restrictHomo (sub :< t) (Keep thin1) (Drop thin2) = restrictHomo sub thin1 thin2
restrictHomo (sub :< t) (Keep thin1) (Keep thin2) = cong (:< t) $ restrictHomo sub thin1 thin2
wknAllRestrict :
(thin1 : ctx `Thins` ctx') ->
(sub : Terms ctx'' ctx') ->
(thin2 : ctx'' `Thins` ctx''') ->
restrict (wknAll sub thin2) thin1 = wknAll (restrict sub thin1) thin2
wknAllRestrict thin1 (Base thin) thin2 = sym $ cong Base $ assoc thin2 thin thin1
wknAllRestrict (Drop thin) (sub :< t) thin2 = wknAllRestrict thin sub thin2
wknAllRestrict (Keep thin) (sub :< t) thin2 = cong (:< wkn t thin2) (wknAllRestrict thin sub thin2)
-- Substitution & Weakening
export
wknSubst :
(t : Term ctx ty) ->
(sub : Terms ctx' ctx) ->
(thin : ctx' `Thins` ctx'') ->
wkn (subst t sub) thin = subst t (wknAll sub thin)
wknSubst (Var i) sub thin =
sym (indexWknAll sub thin i)
wknSubst (Abs t) sub thin =
cong Abs $ Calc $
|~ wkn (subst t (wknAll sub (Drop id) :< Var Here)) (Keep thin)
~~ subst t (wknAll (wknAll sub (Drop id)) (Keep thin) :< Var (index (Keep thin) Here))
...(wknSubst t (wknAll sub (Drop id) :< Var Here) (Keep thin))
~~ subst t (wknAll sub (Keep thin . Drop id) :< Var Here)
...(cong (subst t . (:< Var Here)) (wknAllHomo sub (Drop id) (Keep thin)))
~~ subst t (wknAll sub (Drop id . thin) :< Var Here)
...(cong (subst t . (:< Var Here) . wknAll sub . Drop) $ trans (identityRight thin) (sym $ identityLeft thin))
~~ subst t (wknAll (wknAll sub thin) (Drop id) :< Var Here)
...(sym $ cong (subst t . (:< Var Here)) $ wknAllHomo sub thin (Drop id))
wknSubst (App t u) sub thin =
cong2 App (wknSubst t sub thin) (wknSubst u sub thin)
wknSubst Zero sub thin =
Refl
wknSubst (Suc t) sub thin =
cong Suc (wknSubst t sub thin)
wknSubst (Rec t u v) sub thin =
cong3 Rec (wknSubst t sub thin) (wknSubst u sub thin) (wknSubst v sub thin)
export
substWkn :
(t : Term ctx ty) ->
(thin : ctx `Thins` ctx') ->
(sub : Terms ctx'' ctx') ->
subst (wkn t thin) sub = subst t (restrict sub thin)
substWkn (Var i) thin sub =
sym (indexRestrict thin sub i)
substWkn (Abs t) thin sub =
cong Abs $ Calc $
|~ subst (wkn t $ Keep thin) (wknAll sub (Drop id) :< Var Here)
~~ subst t (restrict (wknAll sub (Drop id)) thin :< Var Here)
...(substWkn t (Keep thin) (wknAll sub (Drop id) :< Var Here))
~~ subst t (wknAll (restrict sub thin) (Drop id) :< Var Here)
...(cong (subst t . (:< Var Here)) $ wknAllRestrict thin sub (Drop id))
substWkn (App t u) thin sub =
cong2 App (substWkn t thin sub) (substWkn u thin sub)
substWkn Zero thin sub =
Refl
substWkn (Suc t) thin sub =
cong Suc (substWkn t thin sub)
substWkn (Rec t u v) thin sub =
cong3 Rec (substWkn t thin sub) (substWkn u thin sub) (substWkn v thin sub)
namespace Equiv
public export
data Equiv : Terms ctx' ctx -> Terms ctx' ctx -> Type where
Base : Equiv (Base (Keep thin)) (Base (Drop thin) :< Var Here)
WknAll :
(len : Len ctx) =>
Equiv sub sub' ->
Equiv
(wknAll sub (Drop $ id @{len}) :< Var Here)
(wknAll sub' (Drop $ id @{len}) :< Var Here)
%name Equiv prf
indexCong : Equiv sub sub' -> (i : Elem ty ctx) -> index sub i = index sub' i
indexCong Base Here = Refl
indexCong Base (There i) = Refl
indexCong (WknAll prf) Here = Refl
indexCong (WknAll {sub, sub'} prf) (There i) = Calc $
|~ index (wknAll sub (Drop id)) i
~~ wkn (index sub i) (Drop id) ...(indexWknAll sub (Drop id) i)
~~ wkn (index sub' i) (Drop id) ...(cong (flip wkn (Drop id)) $ indexCong prf i)
~~ index (wknAll sub' (Drop id)) i ...(sym $ indexWknAll sub' (Drop id) i)
substCong :
(len : Len ctx') =>
(t : Term ctx ty) ->
{0 sub, sub' : Terms ctx' ctx} ->
Equiv sub sub' ->
subst t sub = subst t sub'
substCong (Var i) prf = indexCong prf i
substCong (Abs t) prf = cong Abs (substCong t (WknAll prf))
substCong (App t u) prf = cong2 App (substCong t prf) (substCong u prf)
substCong Zero prf = Refl
substCong (Suc t) prf = cong Suc (substCong t prf)
substCong (Rec t u v) prf = cong3 Rec (substCong t prf) (substCong u prf) (substCong v prf)
substBase : (t : Term ctx ty) -> (thin : ctx `Thins` ctx') -> subst t (Base thin) = wkn t thin
substBase (Var i) thin = Refl
substBase (Abs t) thin =
rewrite identityLeft thin in
cong Abs $ Calc $
|~ subst t (Base (Drop thin) :< Var Here)
~~ subst t (Base $ Keep thin) ...(sym $ substCong t Base)
~~ wkn t (Keep thin) ...(substBase t (Keep thin))
substBase (App t u) thin = cong2 App (substBase t thin) (substBase u thin)
substBase Zero thin = Refl
substBase (Suc t) thin = cong Suc (substBase t thin)
substBase (Rec t u v) thin = cong3 Rec (substBase t thin) (substBase u thin) (substBase v thin)
-- Substitution Composition
indexComp :
(sub1 : Terms ctx' ctx) ->
(sub2 : Terms ctx'' ctx') ->
(i : Elem ty ctx) ->
index (sub2 . sub1) i = subst (index sub1 i) sub2
indexComp (Base thin) sub2 i = indexRestrict thin sub2 i
indexComp (sub1 :< t) sub2 Here = Refl
indexComp (sub1 :< t) sub2 (There i) = indexComp sub1 sub2 i
wknAllComp :
(sub1 : Terms ctx' ctx) ->
(sub2 : Terms ctx'' ctx') ->
(thin : ctx'' `Thins` ctx''') ->
wknAll sub2 thin . sub1 = wknAll (sub2 . sub1) thin
wknAllComp (Base thin') sub2 thin = wknAllRestrict thin' sub2 thin
wknAllComp (sub1 :< t) sub2 thin =
cong2 (:<)
(wknAllComp sub1 sub2 thin)
(sym $ wknSubst t sub2 thin)
compDrop :
(sub1 : Terms ctx' ctx) ->
(thin : ctx' `Thins` ctx'') ->
(sub2 : Terms ctx''' ctx'') ->
sub2 . wknAll sub1 thin = restrict sub2 thin . sub1
compDrop (Base thin') thin sub2 = restrictHomo sub2 thin thin'
compDrop (sub1 :< t) thin sub2 = cong2 (:<) (compDrop sub1 thin sub2) (substWkn t thin sub2)
export
compWknAll :
(sub1 : Terms ctx' ctx) ->
(sub2 : Terms ctx''' ctx'') ->
(thin : ctx' `Thins` ctx'') ->
sub2 . wknAll sub1 thin = restrict sub2 thin . sub1
compWknAll (Base thin') sub2 thin = restrictHomo sub2 thin thin'
compWknAll (sub1 :< t) sub2 thin = cong2 (:<) (compWknAll sub1 sub2 thin) (substWkn t thin sub2)
export
baseComp :
(thin : ctx' `Thins` ctx'') ->
(sub : Terms ctx' ctx) ->
Base thin . sub = wknAll sub thin
baseComp thin (Base thin') = Refl
baseComp thin (sub :< t) = cong2 (:<) (baseComp thin sub) (substBase t thin)
-- Substitution
export
substId : (len : Len ctx) => (t : Term ctx ty) -> subst t (Base $ id @{len}) = t
substId (Var i) = cong Var (indexId i)
substId (Abs t) =
rewrite identitySquared len in
cong Abs $ trans (sym $ substCong t Base) (substId t)
substId (App t u) = cong2 App (substId t) (substId u)
substId Zero = Refl
substId (Suc t) = cong Suc (substId t)
substId (Rec t u v) = cong3 Rec (substId t) (substId u) (substId v)
export
substHomo :
(t : Term ctx ty) ->
(sub1 : Terms ctx' ctx) ->
(sub2 : Terms ctx'' ctx') ->
subst (subst t sub1) sub2 = subst t (sub2 . sub1)
substHomo (Var i) sub1 sub2 =
sym $ indexComp sub1 sub2 i
substHomo (Abs t) sub1 sub2 =
cong Abs $ Calc $
|~ subst (subst t (wknAll sub1 (Drop id) :< Var Here)) (wknAll sub2 (Drop id) :< Var Here)
~~ subst t ((wknAll sub2 (Drop id) :< Var Here) . (wknAll sub1 (Drop id) :< Var Here))
...(substHomo t (wknAll sub1 (Drop id) :< Var Here) (wknAll sub2 (Drop id) :< Var Here))
~~ subst t ((wknAll sub2 (Drop id) :< Var Here) . wknAll sub1 (Drop id) :< Var Here)
...(Refl)
~~ subst t (restrict (wknAll sub2 (Drop id)) id . sub1 :< Var Here)
...(cong (subst t . (:< Var Here)) $ compDrop sub1 (Drop id) (wknAll sub2 (Drop id) :< Var Here))
~~ subst t (wknAll sub2 (Drop id) . sub1 :< Var Here)
...(cong (subst t . (:< Var Here) . (. sub1)) $ restrictId (wknAll sub2 (Drop id)))
~~ subst t (wknAll (sub2 . sub1) (Drop id) :< Var Here)
...(cong (subst t . (:< Var Here)) $ wknAllComp sub1 sub2 (Drop id))
substHomo (App t u) sub1 sub2 =
cong2 App (substHomo t sub1 sub2) (substHomo u sub1 sub2)
substHomo Zero sub1 sub2 =
Refl
substHomo (Suc t) sub1 sub2 =
cong Suc (substHomo t sub1 sub2)
substHomo (Rec t u v) sub1 sub2 =
cong3 Rec (substHomo t sub1 sub2) (substHomo u sub1 sub2) (substHomo v sub1 sub2)
|