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
|
(* ************************************************* *)
(* introduction and examples *)
(* ************************************************* *)
(* example of a polymorphic function: identity *)
(* first the identity on natural numbers *)
Definition natid : nat -> nat :=
fun n : nat => n.
Check (natid O).
Eval compute in (natid O).
(* then the identity on booleans *)
Definition boolid: bool -> bool :=
fun b : bool => b.
Check (boolid true).
Eval compute in (boolid true).
(* now the polymorphic identity *)
Definition polyid : forall A : Set, A -> A :=
fun (A : Set) => fun (a : A) => a.
Check polyid.
Check (polyid nat).
Check (polyid nat O).
Eval compute in (polyid nat O).
Check (polyid _ O).
Check (polyid bool).
Check (polyid bool true).
Eval compute in (polyid bool true).
Check (polyid _ true).
(* the following does not work:
Check (polyid _).
because Coq cannot infer what should be on the place of _ *)
(* notation *)
Notation id := (polyid _).
Check (id O).
Eval compute in (id O).
Check (id true).
Eval compute in (id true).
(* example of a polymorphic inductive definition: polylists *)
(* first the lists of natural numbers *)
Inductive natlist : Set :=
natnil : natlist
| natcons : nat -> natlist -> natlist.
(* the list 2;1;0 *)
Check (natcons 2 (natcons 1 (natcons 0 natnil))).
(* then the lists of booleans *)
Inductive boollist : Set :=
boolnil : boollist
| boolcons : bool -> boollist -> boollist.
(* now the polymorphic lists *)
Inductive polylist (X : Set) : Set :=
polynil : polylist X
| polycons : X -> polylist X -> polylist X.
Check polylist.
Check (polylist nat).
Check (polylist bool).
Check polynil.
Check (polynil nat).
Check (polynil bool).
Check polycons.
Check (polycons nat).
Check (polycons bool).
(* again the list 2;1;0 *)
Check (polycons nat 2 (polycons nat 1 (polycons nat 0 (polynil nat)))).
(* we introduce some handy notation *)
Notation ni := (polynil _).
Notation co := (polycons _).
(* and write the list 2;1;0 again *)
Check (co 2 (co 1 (co 0 ni))).
Check (co true (co false ni)).
(* induction principle for polymorphic lists;
more about this later *)
Check polylist_ind.
(* length of lists of natural numbers *)
Fixpoint natlength (l:natlist) {struct l} : nat :=
match l with
natnil => O
| natcons h t => S (natlength t)
end.
Eval compute in (natlength (natcons 2 (natcons 1 (natcons 0 natnil)))).
(* length of polymorphic lists *)
Fixpoint polylength (A:Set)(l:(polylist A)){struct l} : nat :=
match l with
polynil _ => O
| polycons _ h t => S (polylength A t)
end.
(* NB: in the recursive definition,
polynil and polycons do _not_ get an argument A left of =>;
they do get such arguments right of => *)
Eval compute in (polylength nat (polycons nat 2 (polycons nat 1 (polycons nat 0 (polynil nat))))).
Eval compute in (polylength nat (co 2 (co 1 (co 0 ni)))).
Eval compute in (polylength bool (polycons bool true (polycons bool false (polynil bool)))).
Eval compute in (polylength bool (co true (co false ni))).
(* remark1 about Coq notation:
In the definition of polylist
we use a parameter declaration (X:Set).
Alternatively, we could define a type Set -> Type
as follows: *)
Inductive polylistb : Set -> Type :=
polynilb : forall X:Set, polylistb X
| polyconsb: forall X:Set, X -> polylistb X -> polylistb X.
(* but then we get a quite strange induction predicate *)
Check polylistb_ind.
(* so we usually take the first definition *)
(* ************************************************* *)
(* start of the exercises *)
(* ************************************************* *)
(* exercises about polymorphic lists *)
(* see pw04 for similar exercises on natlists *)
(* exercise 1 *)
(* give the definition of polyappend for polymorphic lists *)
(* test it using Eval compute on an example *)
Fixpoint polyappend (X:Set) (k l : polylist X) {struct k} : (polylist X) :=
match k with
polynil _ => l
| polycons _ x xs => co x (polyappend X xs l)
end.
Eval compute in polyappend nat (co 1 (co 2 ni)) (co 3 (co 4 ni)).
(* prove the following lemma, to be used later*)
Lemma append_nil :
forall X:Set, forall l: polylist X,
polyappend X l (polynil X) = l.
Proof.
intros X l.
induction l.
simpl.
reflexivity.
simpl.
rewrite IHl.
reflexivity.
Qed.
(* exercise 3 *)
(* prove the following lemma, to be used later *)
Lemma append_assoc : forall X, forall k l m,
(polyappend X (polyappend X k l) m) = (polyappend X k (polyappend X l m)).
Proof.
intros X k l m.
induction k.
simpl.
reflexivity.
simpl.
rewrite IHk.
reflexivity.
Qed.
(* exercise 4 *)
(* prove the following lemma *)
Lemma length_append :
forall X:Set, forall k l : (polylist X),
polylength X (polyappend X k l) = plus (polylength X k) (polylength X l).
Proof.
intros X k l.
induction k.
simpl.
reflexivity.
simpl.
rewrite IHk.
reflexivity.
Qed.
(* exercise 5 *)
(* give the definition of polyreverse for polymorphic lists *)
(* test it using Eval compute on an example *)
Fixpoint polyreverse (X:Set) (l : polylist X) {struct l} :(polylist X) :=
match l with
polynil _ => ni
| polycons _ x xs => polyappend X (polyreverse X xs) (co x ni)
end.
Eval compute in polyreverse nat (co 1 (co 2 (co 3 ni))).
(* exercise 6 *)
(* prove the following lemma *)
Lemma reverse_append :
forall X:Set, forall k l: (polylist X),
polyreverse X (polyappend X k l) =
polyappend X (polyreverse X l) (polyreverse X k).
Proof.
intros X k l.
induction k.
simpl.
rewrite append_nil.
reflexivity.
simpl.
rewrite IHk.
rewrite append_assoc.
reflexivity.
Qed.
(* exercise 7 *)
(* prove the following lemma *)
(* this does not correspond to a lemma in pw04 *)
Lemma rev_cons_app :
forall X:Set, forall k l : (polylist X), forall x:X,
polyappend X (polyreverse X (polycons X x k)) l =
polyappend X (polyreverse X k) (polycons X x l).
Proof.
intros X k l x.
simpl.
(* Coq accepts, but prover does not accept:
apply append_assoc.
This proves the proposition immediately.
*)
induction k. (* Not actually induction, but this is cleaner than elim *)
simpl.
reflexivity.
simpl.
rewrite append_assoc.
rewrite append_assoc.
rewrite append_assoc.
simpl.
reflexivity.
Qed.
(* exercises about polymorphic pairs *)
(* definition of pairs of natural numbers *)
Inductive natprod : Set :=
| natpair : nat -> nat -> natprod.
Check natpair.
Check natpair 1.
Check (natpair 1 2).
Check natprod_ind.
(* we define the first and second projection *)
Definition natprodfirst (p : natprod) : nat :=
match p with
| natpair x y => x
end.
Eval compute in (natprodfirst (natpair 1 2)).
Definition natprodsecond (p : natprod) : nat :=
match p with
| natpair x y => y
end.
Eval compute in (natprodsecond (natpair 1 2)).
(* exercise 8 *)
(* give a definition prod of polymorphic pairs
where the first element comes from a set X
and the second element comes from a set Y *)
Inductive prod (X Y :Set) : Set :=
| pair : X -> Y -> prod X Y.
(* exercise 9 *)
(* give definitions of the first and second projection *)
Definition fst (X Y : Set) (p: prod X Y) : X :=
match p with
pair _ _ x _ => x
end.
Definition snd (X Y : Set) (p : prod X Y) : Y :=
match p with
pair _ _ _ y => y
end.
(* exercises about polymorphic trees *)
(* definition of natbintrees
with labels on the nodes *)
Inductive natbintree : Set :=
natleaf : natbintree
| natnode : nat -> natbintree -> natbintree -> natbintree.
Check natleaf.
Check (natnode 1 natleaf natleaf).
Check (natnode 2 (natnode 1 natleaf natleaf) (natnode 3 natleaf natleaf)).
(* the last is the tree
2
/ \
1 3
*)
(* exercise 10 *)
(* give the definition polybintree with constructors polyleaf and polynode
of polymorphic binary trees
with labels on the nodes
you may introduce handy notation *)
Inductive polybintree (X : Set) : Set :=
polyleaf : polybintree X
| polynode : X -> polybintree X -> polybintree X -> polybintree X.
(* exercise 11 *)
(* complete the definition of polyflatten
polyflatten puts the labels of a polybintree from left to right in a polylist *)
Fixpoint polyflatten (X:Set) (t:polybintree X) {struct t} : (polylist X) :=
match t with
| polyleaf _ => ni
| polynode _ x l r => polyappend X (polyflatten X l) (co x (polyflatten X r))
end.
(* perform some tests using the trees above *)
Eval compute in polyflatten nat (polyleaf nat).
Eval compute in polyflatten nat (polynode nat 1 (polyleaf nat) (polyleaf nat)).
Eval compute in polyflatten nat (polynode nat 1 (polynode nat 2 (polyleaf nat) (polyleaf nat)) (polynode nat 3 (polyleaf nat) (polyleaf nat))).
|