| author | hoelzl | 
| Thu, 02 Sep 2010 21:08:31 +0200 | |
| changeset 39101 | 606432dd1896 | 
| parent 38857 | 97775f3e8722 | 
| child 39198 | f967a16dfcdd | 
| permissions | -rw-r--r-- | 
| 31596 | 1 | (* Author: Florian Haftmann, TU Muenchen *) | 
| 26348 | 2 | |
| 3 | header {* Finite types as explicit enumerations *}
 | |
| 4 | ||
| 5 | theory Enum | |
| 30663 
0b6aff7451b2
Main is (Complex_Main) base entry point in library theories
 haftmann parents: 
29961diff
changeset | 6 | imports Map Main | 
| 26348 | 7 | begin | 
| 8 | ||
| 9 | subsection {* Class @{text enum} *}
 | |
| 10 | ||
| 29797 | 11 | class enum = | 
| 26348 | 12 | fixes enum :: "'a list" | 
| 33635 | 13 | assumes UNIV_enum: "UNIV = set enum" | 
| 26444 | 14 | and enum_distinct: "distinct enum" | 
| 26348 | 15 | begin | 
| 16 | ||
| 29797 | 17 | subclass finite proof | 
| 18 | qed (simp add: UNIV_enum) | |
| 26444 | 19 | |
| 20 | lemma enum_all: "set enum = UNIV" unfolding UNIV_enum .. | |
| 21 | ||
| 26348 | 22 | lemma in_enum [intro]: "x \<in> set enum" | 
| 23 | unfolding enum_all by auto | |
| 24 | ||
| 25 | lemma enum_eq_I: | |
| 26 | assumes "\<And>x. x \<in> set xs" | |
| 27 | shows "set enum = set xs" | |
| 28 | proof - | |
| 29 | from assms UNIV_eq_I have "UNIV = set xs" by auto | |
| 30 | with enum_all show ?thesis by simp | |
| 31 | qed | |
| 32 | ||
| 33 | end | |
| 34 | ||
| 35 | ||
| 36 | subsection {* Equality and order on functions *}
 | |
| 37 | ||
| 38857 
97775f3e8722
renamed class/constant eq to equal; tuned some instantiations
 haftmann parents: 
37765diff
changeset | 38 | instantiation "fun" :: (enum, equal) equal | 
| 26513 | 39 | begin | 
| 26348 | 40 | |
| 26513 | 41 | definition | 
| 38857 
97775f3e8722
renamed class/constant eq to equal; tuned some instantiations
 haftmann parents: 
37765diff
changeset | 42 | "HOL.equal f g \<longleftrightarrow> (\<forall>x \<in> set enum. f x = g x)" | 
| 26513 | 43 | |
| 31464 | 44 | instance proof | 
| 38857 
97775f3e8722
renamed class/constant eq to equal; tuned some instantiations
 haftmann parents: 
37765diff
changeset | 45 | qed (simp_all add: equal_fun_def enum_all expand_fun_eq) | 
| 26513 | 46 | |
| 47 | end | |
| 26348 | 48 | |
| 38857 
97775f3e8722
renamed class/constant eq to equal; tuned some instantiations
 haftmann parents: 
37765diff
changeset | 49 | lemma [code nbe]: | 
| 
97775f3e8722
renamed class/constant eq to equal; tuned some instantiations
 haftmann parents: 
37765diff
changeset | 50 | "HOL.equal (f :: _ \<Rightarrow> _) f \<longleftrightarrow> True" | 
| 
97775f3e8722
renamed class/constant eq to equal; tuned some instantiations
 haftmann parents: 
37765diff
changeset | 51 | by (fact equal_refl) | 
| 
97775f3e8722
renamed class/constant eq to equal; tuned some instantiations
 haftmann parents: 
37765diff
changeset | 52 | |
| 28562 | 53 | lemma order_fun [code]: | 
| 26348 | 54 | fixes f g :: "'a\<Colon>enum \<Rightarrow> 'b\<Colon>order" | 
| 26968 | 55 | shows "f \<le> g \<longleftrightarrow> list_all (\<lambda>x. f x \<le> g x) enum" | 
| 37601 | 56 | and "f < g \<longleftrightarrow> f \<le> g \<and> list_ex (\<lambda>x. f x \<noteq> g x) enum" | 
| 57 | by (simp_all add: list_all_iff list_ex_iff enum_all expand_fun_eq le_fun_def order_less_le) | |
| 26968 | 58 | |
| 59 | ||
| 60 | subsection {* Quantifiers *}
 | |
| 61 | ||
| 28562 | 62 | lemma all_code [code]: "(\<forall>x. P x) \<longleftrightarrow> list_all P enum" | 
| 26968 | 63 | by (simp add: list_all_iff enum_all) | 
| 64 | ||
| 37601 | 65 | lemma exists_code [code]: "(\<exists>x. P x) \<longleftrightarrow> list_ex P enum" | 
| 66 | by (simp add: list_ex_iff enum_all) | |
| 26348 | 67 | |
| 68 | ||
| 69 | subsection {* Default instances *}
 | |
| 70 | ||
| 26444 | 71 | primrec n_lists :: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list list" where | 
| 72 | "n_lists 0 xs = [[]]" | |
| 73 | | "n_lists (Suc n) xs = concat (map (\<lambda>ys. map (\<lambda>y. y # ys) xs) (n_lists n xs))" | |
| 74 | ||
| 75 | lemma n_lists_Nil [simp]: "n_lists n [] = (if n = 0 then [[]] else [])" | |
| 76 | by (induct n) simp_all | |
| 77 | ||
| 78 | lemma length_n_lists: "length (n_lists n xs) = length xs ^ n" | |
| 33639 
603320b93668
New list theorems; added map_map to simpset, this is the prefered direction; allow sorting by a key
 hoelzl parents: 
33635diff
changeset | 79 | by (induct n) (auto simp add: length_concat o_def listsum_triv) | 
| 26444 | 80 | |
| 81 | lemma length_n_lists_elem: "ys \<in> set (n_lists n xs) \<Longrightarrow> length ys = n" | |
| 82 | by (induct n arbitrary: ys) auto | |
| 83 | ||
| 84 | lemma set_n_lists: "set (n_lists n xs) = {ys. length ys = n \<and> set ys \<subseteq> set xs}"
 | |
| 85 | proof (rule set_ext) | |
| 86 | fix ys :: "'a list" | |
| 87 |   show "ys \<in> set (n_lists n xs) \<longleftrightarrow> ys \<in> {ys. length ys = n \<and> set ys \<subseteq> set xs}"
 | |
| 88 | proof - | |
| 89 | have "ys \<in> set (n_lists n xs) \<Longrightarrow> length ys = n" | |
| 90 | by (induct n arbitrary: ys) auto | |
| 91 | moreover have "\<And>x. ys \<in> set (n_lists n xs) \<Longrightarrow> x \<in> set ys \<Longrightarrow> x \<in> set xs" | |
| 92 | by (induct n arbitrary: ys) auto | |
| 93 | moreover have "set ys \<subseteq> set xs \<Longrightarrow> ys \<in> set (n_lists (length ys) xs)" | |
| 94 | by (induct ys) auto | |
| 95 | ultimately show ?thesis by auto | |
| 96 | qed | |
| 97 | qed | |
| 98 | ||
| 99 | lemma distinct_n_lists: | |
| 100 | assumes "distinct xs" | |
| 101 | shows "distinct (n_lists n xs)" | |
| 102 | proof (rule card_distinct) | |
| 103 | from assms have card_length: "card (set xs) = length xs" by (rule distinct_card) | |
| 104 | have "card (set (n_lists n xs)) = card (set xs) ^ n" | |
| 105 | proof (induct n) | |
| 106 | case 0 then show ?case by simp | |
| 107 | next | |
| 108 | case (Suc n) | |
| 109 | moreover have "card (\<Union>ys\<in>set (n_lists n xs). (\<lambda>y. y # ys) ` set xs) | |
| 110 | = (\<Sum>ys\<in>set (n_lists n xs). card ((\<lambda>y. y # ys) ` set xs))" | |
| 111 | by (rule card_UN_disjoint) auto | |
| 112 | moreover have "\<And>ys. card ((\<lambda>y. y # ys) ` set xs) = card (set xs)" | |
| 113 | by (rule card_image) (simp add: inj_on_def) | |
| 114 | ultimately show ?case by auto | |
| 115 | qed | |
| 116 | also have "\<dots> = length xs ^ n" by (simp add: card_length) | |
| 117 | finally show "card (set (n_lists n xs)) = length (n_lists n xs)" | |
| 118 | by (simp add: length_n_lists) | |
| 119 | qed | |
| 120 | ||
| 121 | lemma map_of_zip_enum_is_Some: | |
| 122 | assumes "length ys = length (enum \<Colon> 'a\<Colon>enum list)" | |
| 123 | shows "\<exists>y. map_of (zip (enum \<Colon> 'a\<Colon>enum list) ys) x = Some y" | |
| 124 | proof - | |
| 125 | from assms have "x \<in> set (enum \<Colon> 'a\<Colon>enum list) \<longleftrightarrow> | |
| 126 | (\<exists>y. map_of (zip (enum \<Colon> 'a\<Colon>enum list) ys) x = Some y)" | |
| 127 | by (auto intro!: map_of_zip_is_Some) | |
| 128 | then show ?thesis using enum_all by auto | |
| 129 | qed | |
| 130 | ||
| 131 | lemma map_of_zip_enum_inject: | |
| 132 | fixes xs ys :: "'b\<Colon>enum list" | |
| 133 | assumes length: "length xs = length (enum \<Colon> 'a\<Colon>enum list)" | |
| 134 | "length ys = length (enum \<Colon> 'a\<Colon>enum list)" | |
| 135 | and map_of: "the \<circ> map_of (zip (enum \<Colon> 'a\<Colon>enum list) xs) = the \<circ> map_of (zip (enum \<Colon> 'a\<Colon>enum list) ys)" | |
| 136 | shows "xs = ys" | |
| 137 | proof - | |
| 138 | have "map_of (zip (enum \<Colon> 'a list) xs) = map_of (zip (enum \<Colon> 'a list) ys)" | |
| 139 | proof | |
| 140 | fix x :: 'a | |
| 141 | from length map_of_zip_enum_is_Some obtain y1 y2 | |
| 142 | where "map_of (zip (enum \<Colon> 'a list) xs) x = Some y1" | |
| 143 | and "map_of (zip (enum \<Colon> 'a list) ys) x = Some y2" by blast | |
| 144 | moreover from map_of have "the (map_of (zip (enum \<Colon> 'a\<Colon>enum list) xs) x) = the (map_of (zip (enum \<Colon> 'a\<Colon>enum list) ys) x)" | |
| 145 | by (auto dest: fun_cong) | |
| 146 | ultimately show "map_of (zip (enum \<Colon> 'a\<Colon>enum list) xs) x = map_of (zip (enum \<Colon> 'a\<Colon>enum list) ys) x" | |
| 147 | by simp | |
| 148 | qed | |
| 149 | with length enum_distinct show "xs = ys" by (rule map_of_zip_inject) | |
| 150 | qed | |
| 151 | ||
| 152 | instantiation "fun" :: (enum, enum) enum | |
| 153 | begin | |
| 154 | ||
| 155 | definition | |
| 37765 | 156 | "enum = map (\<lambda>ys. the o map_of (zip (enum\<Colon>'a list) ys)) (n_lists (length (enum\<Colon>'a\<Colon>enum list)) enum)" | 
| 26444 | 157 | |
| 158 | instance proof | |
| 159 |   show "UNIV = set (enum \<Colon> ('a \<Rightarrow> 'b) list)"
 | |
| 160 | proof (rule UNIV_eq_I) | |
| 161 | fix f :: "'a \<Rightarrow> 'b" | |
| 162 | have "f = the \<circ> map_of (zip (enum \<Colon> 'a\<Colon>enum list) (map f enum))" | |
| 163 | by (auto simp add: map_of_zip_map expand_fun_eq) | |
| 164 | then show "f \<in> set enum" | |
| 165 | by (auto simp add: enum_fun_def set_n_lists) | |
| 166 | qed | |
| 167 | next | |
| 168 | from map_of_zip_enum_inject | |
| 169 |   show "distinct (enum \<Colon> ('a \<Rightarrow> 'b) list)"
 | |
| 170 | by (auto intro!: inj_onI simp add: enum_fun_def | |
| 171 | distinct_map distinct_n_lists enum_distinct set_n_lists enum_all) | |
| 172 | qed | |
| 173 | ||
| 174 | end | |
| 175 | ||
| 38857 
97775f3e8722
renamed class/constant eq to equal; tuned some instantiations
 haftmann parents: 
37765diff
changeset | 176 | lemma enum_fun_code [code]: "enum = (let enum_a = (enum \<Colon> 'a\<Colon>{enum, equal} list)
 | 
| 28245 
9767dd8e1e54
celver code lemma avoid type ambiguity problem with Haskell
 haftmann parents: 
27487diff
changeset | 177 | in map (\<lambda>ys. the o map_of (zip enum_a ys)) (n_lists (length enum_a) enum))" | 
| 
9767dd8e1e54
celver code lemma avoid type ambiguity problem with Haskell
 haftmann parents: 
27487diff
changeset | 178 | by (simp add: enum_fun_def Let_def) | 
| 26444 | 179 | |
| 26348 | 180 | instantiation unit :: enum | 
| 181 | begin | |
| 182 | ||
| 183 | definition | |
| 184 | "enum = [()]" | |
| 185 | ||
| 31464 | 186 | instance proof | 
| 187 | qed (simp_all add: enum_unit_def UNIV_unit) | |
| 26348 | 188 | |
| 189 | end | |
| 190 | ||
| 191 | instantiation bool :: enum | |
| 192 | begin | |
| 193 | ||
| 194 | definition | |
| 195 | "enum = [False, True]" | |
| 196 | ||
| 31464 | 197 | instance proof | 
| 198 | qed (simp_all add: enum_bool_def UNIV_bool) | |
| 26348 | 199 | |
| 200 | end | |
| 201 | ||
| 202 | primrec product :: "'a list \<Rightarrow> 'b list \<Rightarrow> ('a \<times> 'b) list" where
 | |
| 203 | "product [] _ = []" | |
| 204 | | "product (x#xs) ys = map (Pair x) ys @ product xs ys" | |
| 205 | ||
| 206 | lemma product_list_set: | |
| 207 | "set (product xs ys) = set xs \<times> set ys" | |
| 208 | by (induct xs) auto | |
| 209 | ||
| 26444 | 210 | lemma distinct_product: | 
| 211 | assumes "distinct xs" and "distinct ys" | |
| 212 | shows "distinct (product xs ys)" | |
| 213 | using assms by (induct xs) | |
| 214 | (auto intro: inj_onI simp add: product_list_set distinct_map) | |
| 215 | ||
| 37678 
0040bafffdef
"prod" and "sum" replace "*" and "+" respectively
 haftmann parents: 
37601diff
changeset | 216 | instantiation prod :: (enum, enum) enum | 
| 26348 | 217 | begin | 
| 218 | ||
| 219 | definition | |
| 220 | "enum = product enum enum" | |
| 221 | ||
| 222 | instance by default | |
| 26444 | 223 | (simp_all add: enum_prod_def product_list_set distinct_product enum_all enum_distinct) | 
| 26348 | 224 | |
| 225 | end | |
| 226 | ||
| 37678 
0040bafffdef
"prod" and "sum" replace "*" and "+" respectively
 haftmann parents: 
37601diff
changeset | 227 | instantiation sum :: (enum, enum) enum | 
| 26348 | 228 | begin | 
| 229 | ||
| 230 | definition | |
| 231 | "enum = map Inl enum @ map Inr enum" | |
| 232 | ||
| 233 | instance by default | |
| 26444 | 234 | (auto simp add: enum_all enum_sum_def, case_tac x, auto intro: inj_onI simp add: distinct_map enum_distinct) | 
| 26348 | 235 | |
| 236 | end | |
| 237 | ||
| 238 | primrec sublists :: "'a list \<Rightarrow> 'a list list" where | |
| 239 | "sublists [] = [[]]" | |
| 240 | | "sublists (x#xs) = (let xss = sublists xs in map (Cons x) xss @ xss)" | |
| 241 | ||
| 26444 | 242 | lemma length_sublists: | 
| 243 | "length (sublists xs) = Suc (Suc (0\<Colon>nat)) ^ length xs" | |
| 244 | by (induct xs) (simp_all add: Let_def) | |
| 245 | ||
| 26348 | 246 | lemma sublists_powset: | 
| 26444 | 247 | "set ` set (sublists xs) = Pow (set xs)" | 
| 26348 | 248 | proof - | 
| 249 | have aux: "\<And>x A. set ` Cons x ` A = insert x ` set ` A" | |
| 250 | by (auto simp add: image_def) | |
| 26444 | 251 | have "set (map set (sublists xs)) = Pow (set xs)" | 
| 26348 | 252 | by (induct xs) | 
| 33639 
603320b93668
New list theorems; added map_map to simpset, this is the prefered direction; allow sorting by a key
 hoelzl parents: 
33635diff
changeset | 253 | (simp_all add: aux Let_def Pow_insert Un_commute comp_def del: map_map) | 
| 26444 | 254 | then show ?thesis by simp | 
| 255 | qed | |
| 256 | ||
| 257 | lemma distinct_set_sublists: | |
| 258 | assumes "distinct xs" | |
| 259 | shows "distinct (map set (sublists xs))" | |
| 260 | proof (rule card_distinct) | |
| 261 | have "finite (set xs)" by rule | |
| 262 | then have "card (Pow (set xs)) = Suc (Suc 0) ^ card (set xs)" by (rule card_Pow) | |
| 263 | with assms distinct_card [of xs] | |
| 264 | have "card (Pow (set xs)) = Suc (Suc 0) ^ length xs" by simp | |
| 265 | then show "card (set (map set (sublists xs))) = length (map set (sublists xs))" | |
| 266 | by (simp add: sublists_powset length_sublists) | |
| 26348 | 267 | qed | 
| 268 | ||
| 269 | instantiation nibble :: enum | |
| 270 | begin | |
| 271 | ||
| 272 | definition | |
| 273 | "enum = [Nibble0, Nibble1, Nibble2, Nibble3, Nibble4, Nibble5, Nibble6, Nibble7, | |
| 274 | Nibble8, Nibble9, NibbleA, NibbleB, NibbleC, NibbleD, NibbleE, NibbleF]" | |
| 275 | ||
| 31464 | 276 | instance proof | 
| 277 | qed (simp_all add: enum_nibble_def UNIV_nibble) | |
| 26348 | 278 | |
| 279 | end | |
| 280 | ||
| 281 | instantiation char :: enum | |
| 282 | begin | |
| 283 | ||
| 284 | definition | |
| 37765 | 285 | "enum = map (split Char) (product enum enum)" | 
| 26444 | 286 | |
| 31482 | 287 | lemma enum_chars [code]: | 
| 288 | "enum = chars" | |
| 289 | unfolding enum_char_def chars_def enum_nibble_def by simp | |
| 26348 | 290 | |
| 31464 | 291 | instance proof | 
| 292 | qed (auto intro: char.exhaust injI simp add: enum_char_def product_list_set enum_all full_SetCompr_eq [symmetric] | |
| 293 | distinct_map distinct_product enum_distinct) | |
| 26348 | 294 | |
| 295 | end | |
| 296 | ||
| 29024 | 297 | instantiation option :: (enum) enum | 
| 298 | begin | |
| 299 | ||
| 300 | definition | |
| 301 | "enum = None # map Some enum" | |
| 302 | ||
| 31464 | 303 | instance proof | 
| 304 | qed (auto simp add: enum_all enum_option_def, rule option.exhaust, auto intro: simp add: distinct_map enum_distinct) | |
| 29024 | 305 | |
| 306 | end | |
| 307 | ||
| 308 | end |