Skip to content

Commit be238fa

Browse files
authored
Merge pull request #29 from idris-hackers/feature/maps/edit
Maps: minor editing
2 parents 19efe83 + 463e048 commit be238fa

File tree

1 file changed

+77
-50
lines changed

1 file changed

+77
-50
lines changed

src/Maps.lidr

Lines changed: 77 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
= Maps: Total and Partial Maps
22

33
> module Maps
4+
>
45

56
Maps (or dictionaries) are ubiquitous data structures both generally and in the
67
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.
5253

5354
> data Id : Type where
5455
> MkId : String -> Id
55-
56+
>
5657
> beq_id : (x1, x2 : Id) -> Bool
5758
> beq_id (MkId n1) (MkId n2) = decAsBool $ decEq n1 n2
59+
>
5860

5961
\todo[inline]{Edit}
6062

@@ -68,8 +70,9 @@ present purposes you can think of it as just a fancy \idr{Bool}.)
6870

6971
> beq_id_refl : (x : Id) -> True = beq_id x x
7072
> beq_id_refl (MkId n) with (decEq n n)
71-
> beq_id_refl _ | Yes _ = Refl
73+
> beq_id_refl _ | Yes _ = Refl
7274
> beq_id_refl _ | No contra = absurd $ contra Refl
75+
>
7376

7477
The following useful property of \idr{beq_id} follows from an analogous lemma
7578
about strings:
@@ -78,25 +81,33 @@ about strings:
7881

7982
> iff : {p,q : Type} -> Type
8083
> iff {p} {q} = (p -> q, q -> p)
81-
84+
>
8285
> syntax [p] "<->" [q] = iff {p} {q}
86+
>
8387

84-
\todo[inline]{Somehow this doesn't work if put under \idr{where} as usual}
88+
\todo[inline]{Remove when a release with
89+
https://github.com/idris-lang/Idris-dev/pull/3925 happens}
8590

86-
> bto : (beq_id x y = True) -> x = y
87-
> bto {x=MkId n1} {y=MkId n2} prf with (decEq n1 n2)
88-
> bto Refl | (Yes eq) = cong {f=MkId} eq
89-
> bto prf | (No _) = absurd prf
90-
> bfro : (x = y) -> beq_id x y = True
91-
> bfro {x=MkId n1} {y=MkId n2} prf with (decEq n1 n2)
92-
> bfro _ | (Yes _) = Refl
93-
> bfro prf | (No contra) = absurd $ contra $ idInj prf
94-
> where
95-
> idInj : MkId x = MkId y -> x = y
96-
> idInj Refl = Refl
91+
> Uninhabited (False = True) where
92+
> uninhabited Refl impossible
93+
>
9794

9895
> beq_id_true_iff : (beq_id x y = True) <-> x = y
9996
> beq_id_true_iff = (bto, bfro)
97+
> where
98+
> bto : (beq_id x y = True) -> x = y
99+
> bto {x=MkId n1} {y=MkId n2} prf with (decEq n1 n2)
100+
> bto Refl | Yes eq = cong {f=MkId} eq
101+
> bto prf | No _ = absurd prf
102+
>
103+
> idInj : MkId x = MkId y -> x = y
104+
> idInj Refl = Refl
105+
>
106+
> bfro : (x = y) -> beq_id x y = True
107+
> bfro {x=MkId n1} {y=MkId n2} prf with (decEq n1 n2)
108+
> bfro _ | Yes _ = Refl
109+
> bfro prf | No contra = absurd $ contra $ idInj prf
110+
>
100111

101112
Similarly:
102113

@@ -106,17 +117,20 @@ for now}
106117
> not_true_and_false : (b = False) -> Not (b = True)
107118
> not_true_and_false {b=False} _ Refl impossible
108119
> not_true_and_false {b=True} Refl _ impossible
120+
>
109121
> not_true_is_false : Not (b = True) -> b = False
110122
> not_true_is_false {b=False} h = Refl
111-
> not_true_is_false {b=True} h = absurd $ h Refl
112-
123+
> not_true_is_false {b=True} h = absurd $ h Refl
124+
>
113125
> beq_id_false_iff : (beq_id x y = False) <-> Not (x = y)
114126
> beq_id_false_iff = (to, fro)
115-
> where
116-
> to : (beq_id x y = False) -> Not (x = y)
117-
> to beqf = not_true_and_false beqf . bfro
118-
> fro : (Not (x = y)) -> beq_id x y = False
119-
> fro noteq = not_true_is_false $ noteq . bto
127+
> where
128+
> to : (beq_id x y = False) -> Not (x = y)
129+
> to beqf = not_true_and_false beqf . (snd beq_id_true_iff)
130+
>
131+
> fro : (Not (x = y)) -> beq_id x y = False
132+
> fro noteq = not_true_is_false $ noteq . (fst beq_id_true_iff)
133+
>
120134

121135

122136
== Total Maps
@@ -135,17 +149,19 @@ simplifies proofs that use maps.
135149
We build partial maps in two steps. First, we define a type of _total maps_ that
136150
return a default value when we look up a key that is not present in the map.
137151

138-
> total_map : Type -> Type
139-
> total_map a = Id -> a
152+
> TotalMap : Type -> Type
153+
> TotalMap a = Id -> a
154+
>
140155

141156
Intuitively, a total map over an element type \idr{a} is just a function that
142157
can be used to look up \idr{Id}s, yielding \idr{a}s.
143158

144159
The function \idr{t_empty} yields an empty total map, given a default element;
145160
this map always returns the default element when applied to any id.
146161

147-
> t_empty : (v : a) -> total_map a
162+
> t_empty : (v : a) -> TotalMap a
148163
> t_empty v = \_ => v
164+
>
149165

150166
We can also write this as:
151167

@@ -157,8 +173,9 @@ More interesting is the \idr{update} function, which (as before) takes a map
157173
\idr{m}, a key \idr{x}, and a value \idr{v} and returns a new map that takes
158174
\idr{x} to \idr{v} and takes every other key to whatever \idr{m} does.
159175

160-
> t_update : (x : Id) -> (v : a) -> (m : total_map a) -> total_map a
176+
> t_update : (x : Id) -> (v : a) -> (m : TotalMap a) -> TotalMap a
161177
> t_update x v m = \x' => if beq_id x x' then v else m x'
178+
>
162179

163180
This definition is a nice example of higher-order programming: \idr{t_update}
164181
takes a _function_ \idr{m} and yields a new function \idr{\x' => ...} that
@@ -170,25 +187,27 @@ this:
170187

171188
\todo[inline]{Seems like a wrong description in the book here}
172189

173-
> examplemap : total_map Bool
190+
> examplemap : TotalMap Bool
174191
> examplemap = t_update (MkId "foo") False $
175192
> t_update (MkId "bar") True $
176193
> t_empty False
194+
>
177195

178196
This completes the definition of total maps. Note that we don't need to define a
179197
\idr{find} operation because it is just function application!
180198

181199
> update_example1 : examplemap (MkId "baz") = False
182200
> update_example1 = Refl
183-
201+
>
184202
> update_example2 : examplemap (MkId "foo") = False
185203
> update_example2 = Refl
186-
204+
>
187205
> update_example3 : examplemap (MkId "quux") = False
188206
> update_example3 = Refl
189-
207+
>
190208
> update_example4 : examplemap (MkId "bar") = True
191209
> update_example4 = Refl
210+
>
192211

193212
To use maps in later chapters, we'll need several fundamental facts about how
194213
they behave. Even if you don't work the following exercises, make sure you
@@ -202,6 +221,7 @@ First, the empty map returns its default element for all keys:
202221

203222
> t_apply_empty : t_empty v x = v
204223
> t_apply_empty = ?t_apply_empty_rhs
224+
>
205225

206226
$\square$
207227

@@ -214,6 +234,7 @@ then look up \idr{x} in the map resulting from the \idr{update}, we get back
214234

215235
> t_update_eq : (t_update x v m) x = v
216236
> t_update_eq = ?t_update_eq_rhs
237+
>
217238

218239
$\square$
219240

@@ -226,6 +247,7 @@ a _different_ key \idr{x2} in the resulting map, we get the same result that
226247

227248
> t_update_neq : Not (x1 = x2) -> (t_update x1 v m) x2 = m x2
228249
> t_update_neq neq = ?t_update_neq_rhs
250+
>
229251

230252
$\square$
231253

@@ -239,6 +261,7 @@ simpler map obtained by performing just the second \idr{update} on \idr{m}:
239261

240262
> t_update_shadow : t_update x v2 $ t_update x v1 m = t_update x v2 m
241263
> t_update_shadow = ?t_update_shadow_rhs
264+
>
242265

243266
$\square$
244267

@@ -258,9 +281,10 @@ following:
258281
> data Reflect : Type -> Bool -> Type where
259282
> ReflectT : (p : Type) -> Reflect p True
260283
> ReflectF : (p : Type) -> (Not p) -> Reflect p False
261-
284+
>
262285
> beq_idP : Reflect (x = y) (beq_id x y)
263286
> beq_idP = ?beq_idP_rhs
287+
>
264288

265289
$\square$
266290

@@ -279,6 +303,7 @@ the following theorem, which states that if we update a map to assign key
279303

280304
> t_update_same : t_update x (m x) m = m
281305
> t_update_same = ?t_update_same_rhs
306+
>
282307

283308
$\square$
284309

@@ -292,6 +317,7 @@ we do the updates.
292317
> t_update_permute : Not (x2 = x1) -> t_update x1 v1 $ t_update x2 v2 m
293318
> = t_update x2 v2 $ t_update x1 v1 m
294319
> t_update_permute neq = ?t_update_permute_rhs
320+
>
295321

296322
$\square$
297323

@@ -302,44 +328,45 @@ Finally, we define _partial maps_ on top of total maps. A partial map with
302328
elements of type \idr{a} is simply a total map with elements of type \idr{Maybe
303329
a} and default element \idr{Nothing}.
304330

305-
> partial_map : Type -> Type
306-
> partial_map a = total_map (Maybe a)
307-
308-
> empty : partial_map a
331+
> PartialMap : Type -> Type
332+
> PartialMap a = TotalMap (Maybe a)
333+
>
334+
> empty : PartialMap a
309335
> empty = t_empty Nothing
310-
311-
> update : (x : Id) -> (v : a) -> (m : partial_map a) -> partial_map a
336+
>
337+
> update : (x : Id) -> (v : a) -> (m : PartialMap a) -> PartialMap a
312338
> update x v m = t_update x (Just v) m
339+
>
313340

314341
We now straightforwardly lift all of the basic lemmas about total maps to
315342
partial maps.
316343

317344
> apply_empty : empty {a} x = Nothing {a}
318345
> apply_empty = Refl
319-
346+
>
320347
> update_eq : (update x v m) x = Just v
321348
> update_eq {x} {v} {m} =
322349
> rewrite t_update_eq {x} {v=Just v} {m} in
323-
> Refl
324-
350+
> Refl
351+
>
325352
> update_neq : Not (x2 = x1) -> (update x2 v m) x1 = m x1
326353
> update_neq {x1} {x2} {v} {m} neq =
327354
> rewrite t_update_neq neq {x1=x2} {x2=x1} {v=Just v} {m} in
328-
> Refl
329-
355+
> Refl
356+
>
330357
> update_shadow : update x v2 $ update x v1 m = update x v2 m
331358
> update_shadow {x} {v1} {v2} {m} =
332359
> rewrite t_update_shadow {x} {v1=Just v1} {v2=Just v2} {m} in
333-
> Refl
334-
360+
> Refl
361+
>
335362
> update_same : m x = Just v -> update x v m = m
336-
> update_same {x} {m} {v} prf =
363+
> update_same {x} {m} prf =
337364
> rewrite sym prf in
338365
> rewrite t_update_same {x} {m} in
339-
> Refl
340-
366+
> Refl
367+
>
341368
> update_permute : Not (x2 = x1) -> update x1 v1 $ update x2 v2 m
342369
> = update x2 v2 $ update x1 v1 m
343-
> update_permute {x1} {x2} {v1} {v2} {m} neq =
344-
> rewrite t_update_permute neq {x1} {x2} {v1=Just v1} {v2=Just v2} {m} in
345-
> Refl
370+
> update_permute {v1} {v2} {m} neq =
371+
> rewrite t_update_permute neq {v1=Just v1} {v2=Just v2} {m} in
372+
> Refl

0 commit comments

Comments
 (0)