1
1
= Maps : Total and Partial Maps
2
2
3
3
> module Maps
4
+ >
4
5
5
6
Maps (or dictionaries) are ubiquitous data structures both generally and in the
6
7
theory of programming languages in particular; we're going to need them in many
@@ -52,9 +53,10 @@ equality comparison function for \idr{Id} and its fundamental property.
52
53
53
54
> data Id : Type where
54
55
> MkId : String -> Id
55
-
56
+ >
56
57
> beq_id : (x1, x2 : Id) -> Bool
57
58
> beq_id (MkId n1) (MkId n2) = decAsBool $ decEq n1 n2
59
+ >
58
60
59
61
\ todo[inline]{Edit }
60
62
@@ -68,8 +70,9 @@ present purposes you can think of it as just a fancy \idr{Bool}.)
68
70
69
71
> beq_id_refl : (x : Id) -> True = beq_id x x
70
72
> beq_id_refl (MkId n) with (decEq n n)
71
- > beq_id_refl _ | Yes _ = Refl
73
+ > beq_id_refl _ | Yes _ = Refl
72
74
> beq_id_refl _ | No contra = absurd $ contra Refl
75
+ >
73
76
74
77
The following useful property of \ idr{beq_id} follows from an analogous lemma
75
78
about strings :
@@ -78,8 +81,9 @@ about strings:
78
81
79
82
> iff : {p,q : Type } -> Type
80
83
> iff {p} {q} = (p -> q, q -> p)
81
-
84
+ >
82
85
> syntax [p] " <->" [q] = iff {p} {q}
86
+ >
83
87
84
88
\ todo[inline]{Somehow this doesn't work if put under \ idr{where } as usual}
85
89
@@ -106,10 +110,11 @@ for now}
106
110
> not_true_and_false : (b = False) -> Not (b = True)
107
111
> not_true_and_false {b= False } _ Refl impossible
108
112
> not_true_and_false {b= True } Refl _ impossible
113
+ >
109
114
> not_true_is_false : Not (b = True) -> b = False
110
115
> not_true_is_false {b= False } h = Refl
111
- > not_true_is_false {b= True } h = absurd $ h Refl
112
-
116
+ > not_true_is_false {b= True } h = absurd $ h Refl
117
+ >
113
118
> beq_id_false_iff : (beq_id x y = False) <-> Not (x = y)
114
119
> beq_id_false_iff = (to, fro)
115
120
> where
@@ -137,6 +142,7 @@ return a default value when we look up a key that is not present in the map.
137
142
138
143
> total_map : Type -> Type
139
144
> total_map a = Id -> a
145
+ >
140
146
141
147
Intuitively , a total map over an element type \ idr{a} is just a function that
142
148
can be used to look up \ idr{Id }s, yielding \ idr{a}s.
@@ -146,6 +152,7 @@ this map always returns the default element when applied to any id.
146
152
147
153
> t_empty : (v : a) -> total_map a
148
154
> t_empty v = \ _ => v
155
+ >
149
156
150
157
We can also write this as :
151
158
@@ -159,6 +166,7 @@ More interesting is the \idr{update} function, which (as before) takes a map
159
166
160
167
> t_update : (x : Id) -> (v : a) -> (m : total_map a) -> total_map a
161
168
> t_update x v m = \ x' => if beq_id x x' then v else m x'
169
+ >
162
170
163
171
This definition is a nice example of higher- order programming : \idr{t_update}
164
172
takes a _function_ \ idr{m} and yields a new function \ idr{\ x' => ... } that
@@ -174,21 +182,23 @@ this:
174
182
> examplemap = t_update (MkId " foo" ) False $
175
183
> t_update (MkId " bar" ) True $
176
184
> t_empty False
185
+ >
177
186
178
187
This completes the definition of total maps. Note that we don't need to define a
179
188
\ idr{find} operation because it is just function application!
180
189
181
190
> update_example1 : examplemap (MkId "baz") = False
182
191
> update_example1 = Refl
183
-
192
+ >
184
193
> update_example2 : examplemap (MkId "foo") = False
185
194
> update_example2 = Refl
186
-
195
+ >
187
196
> update_example3 : examplemap (MkId "quux") = False
188
197
> update_example3 = Refl
189
-
198
+ >
190
199
> update_example4 : examplemap (MkId "bar") = True
191
200
> update_example4 = Refl
201
+ >
192
202
193
203
To use maps in later chapters, we'll need several fundamental facts about how
194
204
they behave. Even if you don't work the following exercises, make sure you
@@ -202,6 +212,7 @@ First, the empty map returns its default element for all keys:
202
212
203
213
> t_apply_empty : t_empty v x = v
204
214
> t_apply_empty = ? t_apply_empty_rhs
215
+ >
205
216
206
217
$\ square$
207
218
@@ -214,6 +225,7 @@ then look up \idr{x} in the map resulting from the \idr{update}, we get back
214
225
215
226
> t_update_eq : (t_update x v m) x = v
216
227
> t_update_eq = ? t_update_eq_rhs
228
+ >
217
229
218
230
$\ square$
219
231
@@ -226,6 +238,7 @@ a _different_ key \idr{x2} in the resulting map, we get the same result that
226
238
227
239
> t_update_neq : Not (x1 = x2) -> (t_update x1 v m) x2 = m x2
228
240
> t_update_neq neq = ? t_update_neq_rhs
241
+ >
229
242
230
243
$\ square$
231
244
@@ -239,6 +252,7 @@ simpler map obtained by performing just the second \idr{update} on \idr{m}:
239
252
240
253
> t_update_shadow : t_update x v2 $ t_update x v1 m = t_update x v2 m
241
254
> t_update_shadow = ? t_update_shadow_rhs
255
+ >
242
256
243
257
$\ square$
244
258
@@ -258,9 +272,10 @@ following:
258
272
> data Reflect : Type -> Bool -> Type where
259
273
> ReflectT : (p : Type ) -> Reflect p True
260
274
> ReflectF : (p : Type ) -> (Not p) -> Reflect p False
261
-
275
+ >
262
276
> beq_idP : Reflect (x = y) (beq_id x y)
263
277
> beq_idP = ? beq_idP_rhs
278
+ >
264
279
265
280
$\ square$
266
281
@@ -279,6 +294,7 @@ the following theorem, which states that if we update a map to assign key
279
294
280
295
> t_update_same : t_update x (m x) m = m
281
296
> t_update_same = ? t_update_same_rhs
297
+ >
282
298
283
299
$\ square$
284
300
@@ -292,6 +308,7 @@ we do the updates.
292
308
> t_update_permute : Not (x2 = x1) -> t_update x1 v1 $ t_update x2 v2 m
293
309
> = t_update x2 v2 $ t_update x1 v1 m
294
310
> t_update_permute neq = ? t_update_permute_rhs
311
+ >
295
312
296
313
$\ square$
297
314
@@ -304,40 +321,41 @@ a} and default element \idr{Nothing}.
304
321
305
322
> partial_map : Type -> Type
306
323
> partial_map a = total_map (Maybe a)
307
-
324
+ >
308
325
> empty : partial_map a
309
326
> empty = t_empty Nothing
310
-
327
+ >
311
328
> update : (x : Id) -> (v : a) -> (m : partial_map a) -> partial_map a
312
329
> update x v m = t_update x (Just v) m
330
+ >
313
331
314
332
We now straightforwardly lift all of the basic lemmas about total maps to
315
333
partial maps.
316
334
317
335
> apply_empty : empty {a} x = Nothing {a}
318
336
> apply_empty = Refl
319
-
337
+ >
320
338
> update_eq : (update x v m) x = Just v
321
339
> update_eq {x} {v} {m} =
322
340
> rewrite t_update_eq {x} {v= Just v} {m} in
323
- > Refl
324
-
341
+ > Refl
342
+ >
325
343
> update_neq : Not (x2 = x1) -> (update x2 v m) x1 = m x1
326
344
> update_neq {x1} {x2} {v} {m} neq =
327
345
> rewrite t_update_neq neq {x1= x2} {x2= x1} {v= Just v} {m} in
328
- > Refl
329
-
346
+ > Refl
347
+ >
330
348
> update_shadow : update x v2 $ update x v1 m = update x v2 m
331
349
> update_shadow {x} {v1} {v2} {m} =
332
350
> rewrite t_update_shadow {x} {v1= Just v1} {v2= Just v2} {m} in
333
- > Refl
334
-
351
+ > Refl
352
+ >
335
353
> update_same : m x = Just v -> update x v m = m
336
354
> update_same {x} {m} {v} prf =
337
355
> rewrite sym prf in
338
356
> rewrite t_update_same {x} {m} in
339
- > Refl
340
-
357
+ > Refl
358
+ >
341
359
> update_permute : Not (x2 = x1) -> update x1 v1 $ update x2 v2 m
342
360
> = update x2 v2 $ update x1 v1 m
343
361
> update_permute {x1} {x2} {v1} {v2} {m} neq =
0 commit comments