1 (* ID: $Id$ |
1 (* ID: $Id$ |
2 Author: Florian Haftmann, TU Muenchen |
2 Author: Florian Haftmann, TU Muenchen |
3 *) |
3 *) |
4 |
4 |
5 header {* Collection classes as examples for code generation *} |
5 header {* Collection classes as examples for code generation *} |
6 |
6 |
7 theory CodeCollections |
7 theory CodeCollections |
8 imports Main |
8 imports Main Product_ord List_lexord |
9 begin |
9 begin |
10 |
10 |
11 section {* Collection classes as examples for code generation *} |
11 section {* Collection classes as examples for code generation *} |
12 |
12 |
13 class ordered = eq + |
13 fun |
14 constrains eq :: "'a \<Rightarrow> 'a \<Rightarrow> bool" |
14 abs_sorted :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where |
15 fixes le :: "'a \<Rightarrow> 'a \<Rightarrow> bool" (infix "\<^loc><<=" 65) |
15 "abs_sorted cmp [] \<longleftrightarrow> True" |
16 fixes lt :: "'a \<Rightarrow> 'a \<Rightarrow> bool" (infix "\<^loc><<" 65) |
16 "abs_sorted cmp [x] \<longleftrightarrow> True" |
17 assumes order_refl: "x \<^loc><<= x" |
17 "abs_sorted cmp (x#y#xs) \<longleftrightarrow> cmp x y \<and> abs_sorted cmp (y#xs)" |
18 assumes order_trans: "x \<^loc><<= y ==> y \<^loc><<= z ==> x \<^loc><<= z" |
18 |
19 assumes order_antisym: "x \<^loc><<= y ==> y \<^loc><<= x ==> x = y" |
19 abbreviation (in ord) |
20 |
20 "sorted \<equiv> abs_sorted less_eq" |
21 declare order_refl [simp, intro] |
|
22 |
|
23 defs |
|
24 lt_def: "x << y == (x <<= y \<and> x \<noteq> y)" |
|
25 |
|
26 lemma lt_intro [intro]: |
|
27 assumes "x <<= y" and "x \<noteq> y" |
|
28 shows "x << y" |
|
29 unfolding lt_def .. |
|
30 |
|
31 lemma lt_elim [elim]: |
|
32 assumes "(x::'a::ordered) << y" |
|
33 and Q: "!!x y::'a::ordered. x <<= y \<Longrightarrow> x \<noteq> y \<Longrightarrow> P" |
|
34 shows P |
|
35 proof - |
|
36 from prems have R1: "x <<= y" and R2: "x \<noteq> y" by (simp_all add: lt_def) |
|
37 show P by (rule Q [OF R1 R2]) |
|
38 qed |
|
39 |
|
40 lemma lt_trans: |
|
41 assumes "x << y" and "y << z" |
|
42 shows "x << z" |
|
43 proof |
|
44 from prems lt_def have prems': "x <<= y" "y <<= z" by auto |
|
45 show "x <<= z" by (rule order_trans, auto intro: prems') |
|
46 next |
|
47 show "x \<noteq> z" |
|
48 proof |
|
49 from prems lt_def have prems': "x <<= y" "y <<= z" "x \<noteq> y" by auto |
|
50 assume "x = z" |
|
51 with prems' have "x <<= y" and "y <<= x" by auto |
|
52 with order_antisym have "x = y" . |
|
53 with prems' show False by auto |
|
54 qed |
|
55 qed |
|
56 |
|
57 definition (in ordered) |
|
58 min :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" where |
|
59 "min x y = (if x \<^loc><<= y then x else y)" |
|
60 |
|
61 definition (in ordered) |
|
62 max :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" where |
|
63 "max x y = (if x \<^loc><<= y then y else x)" |
|
64 |
|
65 definition |
|
66 min :: "'a::ordered \<Rightarrow> 'a \<Rightarrow> 'a" where |
|
67 "min x y = (if x <<= y then x else y)" |
|
68 |
|
69 definition |
|
70 max :: "'a::ordered \<Rightarrow> 'a \<Rightarrow> 'a" where |
|
71 "max x y = (if x <<= y then y else x)" |
|
72 |
|
73 fun abs_sorted :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" |
|
74 where |
|
75 "abs_sorted cmp [] = True" |
|
76 | "abs_sorted cmp [x] = True" |
|
77 | "abs_sorted cmp (x#y#xs) = (cmp x y \<and> abs_sorted cmp (y#xs))" |
|
78 |
|
79 thm abs_sorted.simps |
|
80 |
|
81 abbreviation (in ordered) |
|
82 "sorted \<equiv> abs_sorted le" |
|
83 |
21 |
84 abbreviation |
22 abbreviation |
85 "sorted \<equiv> abs_sorted le" |
23 "sorted \<equiv> abs_sorted less_eq" |
86 |
24 |
87 lemma (in ordered) sorted_weakening: |
25 lemma (in partial_order) sorted_weakening: |
88 assumes "sorted (x # xs)" |
26 assumes "sorted (x # xs)" |
89 shows "sorted xs" |
27 shows "sorted xs" |
90 using prems proof (induct xs) |
28 using prems proof (induct xs) |
91 case Nil show ?case by simp |
29 case Nil show ?case by simp |
92 next |
30 next |
93 case (Cons x' xs) |
31 case (Cons x' xs) |
94 from this(5) have "sorted (x # x' # xs)" . |
32 from this have "sorted (x # x' # xs)" by auto |
95 then show "sorted (x' # xs)" |
33 then show "sorted (x' # xs)" |
96 by auto |
34 by auto |
97 qed |
35 qed |
98 |
36 |
99 instance bool :: ordered |
37 instance unit :: order |
100 "p <<= q == (p --> q)" |
38 "u \<le> v \<equiv> True" |
101 by default (unfold ordered_bool_def, blast+) |
39 "u < v \<equiv> False" |
102 |
40 by default (simp_all add: order_unit_def) |
103 instance nat :: ordered |
41 |
104 "m <<= n == m <= n" |
42 fun le_option' :: "'a\<Colon>order option \<Rightarrow> 'a option \<Rightarrow> bool" |
105 by default (simp_all add: ordered_nat_def) |
43 where "le_option' None y \<longleftrightarrow> True" |
106 |
44 | "le_option' (Some x) None \<longleftrightarrow> False" |
107 instance int :: ordered |
45 | "le_option' (Some x) (Some y) \<longleftrightarrow> x \<le> y" |
108 "k <<= l == k <= l" |
46 |
109 by default (simp_all add: ordered_int_def) |
47 instance option :: (order) order |
110 |
48 "x \<le> y \<equiv> le_option' x y" |
111 instance unit :: ordered |
49 "x < y \<equiv> x \<le> y \<and> x \<noteq> y" |
112 "u <<= v == True" |
50 proof (default, unfold order_option_def) |
113 by default (simp_all add: ordered_unit_def) |
|
114 |
|
115 |
|
116 fun le_option' :: "'a::ordered option \<Rightarrow> 'a option \<Rightarrow> bool" |
|
117 where |
|
118 "le_option' None y = True" |
|
119 | "le_option' (Some x) None = False" |
|
120 | "le_option' (Some x) (Some y) = x <<= y" |
|
121 |
|
122 instance option :: (ordered) ordered |
|
123 "x <<= y == le_option' x y" |
|
124 proof (default, unfold ordered_option_def) |
|
125 fix x |
51 fix x |
126 show "le_option' x x" by (cases x) simp_all |
52 show "le_option' x x" by (cases x) simp_all |
127 next |
53 next |
128 fix x y z |
54 fix x y z |
129 assume "le_option' x y" "le_option' y z" |
55 assume "le_option' x y" "le_option' y z" |
130 then show "le_option' x z" |
56 then show "le_option' x z" |
131 by (cases x, simp_all, cases y, simp_all, cases z, simp_all) |
57 by (cases x, simp_all, cases y, simp_all, cases z, simp_all) |
132 (erule order_trans, assumption) |
|
133 next |
58 next |
134 fix x y |
59 fix x y |
135 assume "le_option' x y" "le_option' y x" |
60 assume "le_option' x y" "le_option' y x" |
136 then show "x = y" |
61 then show "x = y" |
137 by (cases x, simp_all, cases y, simp_all, cases y, simp_all) |
62 by (cases x, simp_all, cases y, simp_all, cases y, simp_all) |
138 (erule order_antisym, assumption) |
63 next |
|
64 fix x y |
|
65 show "le_option' x y \<and> x \<noteq> y \<longleftrightarrow> le_option' x y \<and> x \<noteq> y" .. |
139 qed |
66 qed |
140 |
67 |
141 lemma [simp, code]: |
68 lemma [simp, code]: |
142 "None <<= y = True" |
69 "None \<le> y \<longleftrightarrow> True" |
143 "Some x <<= None = False" |
70 "Some x \<le> None \<longleftrightarrow> False" |
144 "Some v <<= Some w = v <<= w" |
71 "Some v \<le> Some w \<longleftrightarrow> v \<le> w" |
145 unfolding ordered_option_def le_option'.simps by rule+ |
72 unfolding order_option_def le_option'.simps by rule+ |
146 |
73 |
147 fun le_pair' :: "'a::ordered \<times> 'b::ordered \<Rightarrow> 'a \<times> 'b \<Rightarrow> bool" |
74 lemma forall_all [simp]: |
148 where |
75 "list_all P xs \<longleftrightarrow> (\<forall>x\<in>set xs. P x)" |
149 "le_pair' (x1, y1) (x2, y2) = (x1 << x2 \<or> x1 = x2 \<and> y1 <<= y2)" |
76 by (induct xs) auto |
150 |
77 |
151 instance * :: (ordered, ordered) ordered |
78 lemma exists_ex [simp]: |
152 "x <<= y == le_pair' x y" |
79 "list_ex P xs \<longleftrightarrow> (\<exists>x\<in>set xs. P x)" |
153 apply (default, unfold "ordered_*_def", unfold split_paired_all) |
80 by (induct xs) auto |
154 apply simp_all |
81 |
155 apply (auto intro: lt_trans order_trans)[1] |
82 class fin = |
156 unfolding lt_def apply (auto intro: order_antisym)[1] |
83 fixes fin :: "'a list" |
157 done |
84 assumes member_fin: "x \<in> set fin" |
158 |
85 begin |
159 lemma [simp, code]: |
86 |
160 "(x1, y1) <<= (x2, y2) = (x1 << x2 \<or> x1 = x2 \<and> y1 <<= y2)" |
87 lemma set_enum_UNIV: |
161 unfolding "ordered_*_def" le_pair'.simps .. |
88 "set fin = UNIV" |
162 |
89 using member_fin by auto |
163 (* |
90 |
164 |
91 lemma all_forall [code func, code inline]: |
165 fun le_list' :: "'a::ordered list \<Rightarrow> 'a list \<Rightarrow> bool" |
92 "(\<forall>x. P x) \<longleftrightarrow> list_all P fin" |
166 where |
93 using set_enum_UNIV by simp_all |
167 "le_list' [] ys = True" |
94 |
168 | "le_list' (x#xs) [] = False" |
95 lemma ex_exists [code func, code inline]: |
169 | "le_list' (x#xs) (y#ys) = (x << y \<or> x = y \<and> le_list' xs ys)" |
96 "(\<exists>x. P x) \<longleftrightarrow> list_ex P fin" |
170 |
97 using set_enum_UNIV by simp_all |
171 instance (ordered) list :: ordered |
98 |
172 "xs <<= ys == le_list' xs ys" |
99 end |
173 proof (default, unfold "ordered_list_def") |
|
174 fix xs |
|
175 show "le_list' xs xs" by (induct xs) simp_all |
|
176 next |
|
177 fix xs ys zs |
|
178 assume "le_list' xs ys" and "le_list' ys zs" |
|
179 then show "le_list' xs zs" |
|
180 apply (induct xs zs rule: le_list'.induct) |
|
181 apply simp_all |
|
182 apply (cases ys) apply simp_all |
|
183 |
100 |
184 apply (induct ys) apply simp_all |
101 instance bool :: fin |
185 apply (induct ys) |
|
186 apply simp_all |
|
187 apply (induct zs) |
|
188 apply simp_all |
|
189 next |
|
190 fix xs ys |
|
191 assume "le_list' xs ys" and "le_list' ys xs" |
|
192 show "xs = ys" sorry |
|
193 qed |
|
194 |
|
195 lemma [simp, code]: |
|
196 "[] <<= ys = True" |
|
197 "(x#xs) <<= [] = False" |
|
198 "(x#xs) <<= (y#ys) = (x << y \<or> x = y \<and> xs <<= ys)" |
|
199 unfolding "ordered_list_def" le_list'.simps by rule+*) |
|
200 |
|
201 class infimum = ordered + |
|
202 fixes inf |
|
203 assumes inf: "inf \<^loc><<= x" |
|
204 |
|
205 lemma (in infimum) |
|
206 assumes prem: "a \<^loc><<= inf" |
|
207 shows no_smaller: "a = inf" |
|
208 using prem inf by (rule order_antisym) |
|
209 |
|
210 |
|
211 ML {* set quick_and_dirty *} |
|
212 function abs_max_of :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a list \<Rightarrow> 'a" |
|
213 where |
|
214 "abs_max_of cmp inff [] = inff" |
|
215 | "abs_max_of cmp inff [x] = x" |
|
216 | "abs_max_of cmp inff (x#xs) = |
|
217 ordered.max cmp x (abs_max_of cmp inff xs)" |
|
218 apply pat_completeness sorry |
|
219 |
|
220 abbreviation (in infimum) |
|
221 "max_of xs \<equiv> abs_max_of le inf" |
|
222 |
|
223 abbreviation |
|
224 "max_of xs \<equiv> abs_max_of le inf" |
|
225 |
|
226 instance bool :: infimum |
|
227 "inf == False" |
|
228 by default (simp add: infimum_bool_def) |
|
229 |
|
230 instance nat :: infimum |
|
231 "inf == 0" |
|
232 by default (simp add: infimum_nat_def) |
|
233 |
|
234 instance unit :: infimum |
|
235 "inf == ()" |
|
236 by default (simp add: infimum_unit_def) |
|
237 |
|
238 instance option :: (ordered) infimum |
|
239 "inf == None" |
|
240 by default (simp add: infimum_option_def) |
|
241 |
|
242 instance * :: (infimum, infimum) infimum |
|
243 "inf == (inf, inf)" |
|
244 by default (unfold "infimum_*_def", unfold split_paired_all, auto intro: inf) |
|
245 |
|
246 class enum = ordered + |
|
247 fixes enum :: "'a list" |
|
248 assumes member_enum: "x \<in> set enum" |
|
249 and ordered_enum: "abs_sorted le enum" |
|
250 |
|
251 (* |
|
252 FIXME: |
|
253 - abbreviations must be propagated before locale introduction |
|
254 - then also now shadowing may occur |
|
255 *) |
|
256 (*abbreviation (in enum) |
|
257 "local.sorted \<equiv> abs_sorted le"*) |
|
258 |
|
259 instance bool :: enum |
|
260 (* FIXME: better name handling of definitions *) |
102 (* FIXME: better name handling of definitions *) |
261 "_1": "enum == [False, True]" |
103 "_1": "fin == [False, True]" |
262 by default (simp_all add: enum_bool_def) |
104 by default (simp_all add: fin_bool_def) |
263 |
105 |
264 instance unit :: enum |
106 instance unit :: fin |
265 "_2": "enum == [()]" |
107 "_2": "fin == [()]" |
266 by default (simp_all add: enum_unit_def) |
108 by default (simp_all add: fin_unit_def) |
267 |
109 |
268 (*consts |
110 fun |
269 product :: "'a list \<Rightarrow> 'b list \<Rightarrow> ('a * 'b) list" |
111 product :: "'a list \<Rightarrow> 'b list \<Rightarrow> ('a * 'b) list" |
270 |
112 where |
271 primrec |
|
272 "product [] ys = []" |
113 "product [] ys = []" |
273 "product (x#xs) ys = map (Pair x) ys @ product xs ys" |
114 "product (x#xs) ys = map (Pair x) ys @ product xs ys" |
274 |
115 |
275 lemma product_all: |
116 lemma product_all: |
276 assumes "x \<in> set xs" "y \<in> set ys" |
117 assumes "x \<in> set xs" "y \<in> set ys" |
292 with Cons have "(x, y) \<in> set (product xs ys)" by auto |
133 with Cons have "(x, y) \<in> set (product xs ys)" by auto |
293 then show "(x, y) \<in> set (product (z#xs) ys)" by auto |
134 then show "(x, y) \<in> set (product (z#xs) ys)" by auto |
294 qed |
135 qed |
295 qed |
136 qed |
296 |
137 |
297 lemma product_sorted: |
138 instance * :: (fin, fin) fin |
298 assumes "sorted xs" "sorted ys" |
139 "_3": "fin == product fin fin" |
299 shows "sorted (product xs ys)" |
|
300 using prems proof (induct xs) |
|
301 case Nil |
|
302 then show ?case by simp |
|
303 next |
|
304 case (Cons x xs) |
|
305 from Cons ordered.sorted_weakening have "sorted xs" by auto |
|
306 with Cons have "sorted (product xs ys)" by auto |
|
307 then show ?case apply simp |
|
308 proof - |
|
309 assume |
|
310 apply simp |
|
311 |
|
312 proof (cases "x = z") |
|
313 case True |
|
314 with Cons have "(x, y) \<in> set (product (x # xs) ys)" by simp |
|
315 with True show ?thesis by simp |
|
316 next |
|
317 case False |
|
318 with Cons have "x \<in> set xs" by auto |
|
319 with Cons have "(x, y) \<in> set (product xs ys)" by auto |
|
320 then show "(x, y) \<in> set (product (z#xs) ys)" by auto |
|
321 qed |
|
322 qed |
|
323 |
|
324 instance (enum, enum) * :: enum |
|
325 "_3": "enum == product enum enum" |
|
326 apply default |
140 apply default |
327 apply (simp_all add: "enum_*_def") |
141 apply (simp_all add: "fin_*_def") |
328 apply (unfold split_paired_all) |
142 apply (unfold split_paired_all) |
329 apply (rule product_all) |
143 apply (rule product_all) |
330 apply (rule member_enum)+ |
144 apply (rule member_fin)+ |
331 sorry*) |
145 done |
332 |
146 |
333 instance option :: (enum) enum |
147 instance option :: (fin) fin |
334 "_4": "enum == None # map Some enum" |
148 "_4": "fin == None # map Some fin" |
335 proof (default, unfold enum_option_def) |
149 proof (default, unfold fin_option_def) |
336 fix x :: "'a::enum option" |
150 fix x :: "'a::fin option" |
337 show "x \<in> set (None # map Some enum)" |
151 show "x \<in> set (None # map Some fin)" |
338 proof (cases x) |
152 proof (cases x) |
339 case None then show ?thesis by auto |
153 case None then show ?thesis by auto |
340 next |
154 next |
341 case (Some x) then show ?thesis by (auto intro: member_enum) |
155 case (Some x) then show ?thesis by (auto intro: member_fin) |
342 qed |
156 qed |
343 next |
157 qed |
344 show "sorted (None # map Some (enum :: ('a::enum) list))" |
|
345 sorry |
|
346 (*proof (cases "enum :: 'a list") |
|
347 case Nil then show ?thesis by simp |
|
348 next |
|
349 case (Cons x xs) |
|
350 then have "sorted (None # map Some (x # xs))" sorry |
|
351 then show ?thesis apply simp |
|
352 apply simp_all |
|
353 apply auto*) |
|
354 qed |
|
355 |
|
356 ML {* reset quick_and_dirty *} |
|
357 |
158 |
358 consts |
159 consts |
359 get_first :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a option" |
160 get_first :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a option" |
360 |
161 |
361 primrec |
162 primrec |