src/HOL/Enum.thy
author bulwahn
Sun Dec 16 18:07:29 2012 +0100 (2012-12-16)
changeset 50567 768a3fbe4149
parent 49972 f11f8905d9fd
child 52435 6646bb548c6b
permissions -rw-r--r--
providing a custom code equation for vimage to overwrite the vimage definition that would be rewritten by set_comprehension_pointfree simproc in the code preprocessor to an non-terminating code equation
     1 (* Author: Florian Haftmann, TU Muenchen *)
     2 
     3 header {* Finite types as explicit enumerations *}
     4 
     5 theory Enum
     6 imports Map
     7 begin
     8 
     9 subsection {* Class @{text enum} *}
    10 
    11 class enum =
    12   fixes enum :: "'a list"
    13   fixes enum_all :: "('a \<Rightarrow> bool) \<Rightarrow> bool"
    14   fixes enum_ex :: "('a \<Rightarrow> bool) \<Rightarrow> bool"
    15   assumes UNIV_enum: "UNIV = set enum"
    16     and enum_distinct: "distinct enum"
    17   assumes enum_all_UNIV: "enum_all P \<longleftrightarrow> Ball UNIV P"
    18   assumes enum_ex_UNIV: "enum_ex P \<longleftrightarrow> Bex UNIV P" 
    19    -- {* tailored towards simple instantiation *}
    20 begin
    21 
    22 subclass finite proof
    23 qed (simp add: UNIV_enum)
    24 
    25 lemma enum_UNIV:
    26   "set enum = UNIV"
    27   by (simp only: UNIV_enum)
    28 
    29 lemma in_enum: "x \<in> set enum"
    30   by (simp add: enum_UNIV)
    31 
    32 lemma enum_eq_I:
    33   assumes "\<And>x. x \<in> set xs"
    34   shows "set enum = set xs"
    35 proof -
    36   from assms UNIV_eq_I have "UNIV = set xs" by auto
    37   with enum_UNIV show ?thesis by simp
    38 qed
    39 
    40 lemma card_UNIV_length_enum:
    41   "card (UNIV :: 'a set) = length enum"
    42   by (simp add: UNIV_enum distinct_card enum_distinct)
    43 
    44 lemma enum_all [simp]:
    45   "enum_all = HOL.All"
    46   by (simp add: fun_eq_iff enum_all_UNIV)
    47 
    48 lemma enum_ex [simp]:
    49   "enum_ex = HOL.Ex" 
    50   by (simp add: fun_eq_iff enum_ex_UNIV)
    51 
    52 end
    53 
    54 
    55 subsection {* Implementations using @{class enum} *}
    56 
    57 subsubsection {* Unbounded operations and quantifiers *}
    58 
    59 lemma Collect_code [code]:
    60   "Collect P = set (filter P enum)"
    61   by (simp add: enum_UNIV)
    62 
    63 lemma vimage_code [code]:
    64   "f -` B = set (filter (%x. f x : B) enum_class.enum)"
    65   unfolding vimage_def Collect_code ..
    66 
    67 definition card_UNIV :: "'a itself \<Rightarrow> nat"
    68 where
    69   [code del]: "card_UNIV TYPE('a) = card (UNIV :: 'a set)"
    70 
    71 lemma [code]:
    72   "card_UNIV TYPE('a :: enum) = card (set (Enum.enum :: 'a list))"
    73   by (simp only: card_UNIV_def enum_UNIV)
    74 
    75 lemma all_code [code]: "(\<forall>x. P x) \<longleftrightarrow> enum_all P"
    76   by simp
    77 
    78 lemma exists_code [code]: "(\<exists>x. P x) \<longleftrightarrow> enum_ex P"
    79   by simp
    80 
    81 lemma exists1_code [code]: "(\<exists>!x. P x) \<longleftrightarrow> list_ex1 P enum"
    82   by (auto simp add: list_ex1_iff enum_UNIV)
    83 
    84 
    85 subsubsection {* An executable choice operator *}
    86 
    87 definition
    88   [code del]: "enum_the = The"
    89 
    90 lemma [code]:
    91   "The P = (case filter P enum of [x] => x | _ => enum_the P)"
    92 proof -
    93   {
    94     fix a
    95     assume filter_enum: "filter P enum = [a]"
    96     have "The P = a"
    97     proof (rule the_equality)
    98       fix x
    99       assume "P x"
   100       show "x = a"
   101       proof (rule ccontr)
   102         assume "x \<noteq> a"
   103         from filter_enum obtain us vs
   104           where enum_eq: "enum = us @ [a] @ vs"
   105           and "\<forall> x \<in> set us. \<not> P x"
   106           and "\<forall> x \<in> set vs. \<not> P x"
   107           and "P a"
   108           by (auto simp add: filter_eq_Cons_iff) (simp only: filter_empty_conv[symmetric])
   109         with `P x` in_enum[of x, unfolded enum_eq] `x \<noteq> a` show "False" by auto
   110       qed
   111     next
   112       from filter_enum show "P a" by (auto simp add: filter_eq_Cons_iff)
   113     qed
   114   }
   115   from this show ?thesis
   116     unfolding enum_the_def by (auto split: list.split)
   117 qed
   118 
   119 code_abort enum_the
   120 code_const enum_the (Eval "(fn p => raise Match)")
   121 
   122 
   123 subsubsection {* Equality and order on functions *}
   124 
   125 instantiation "fun" :: (enum, equal) equal
   126 begin
   127 
   128 definition
   129   "HOL.equal f g \<longleftrightarrow> (\<forall>x \<in> set enum. f x = g x)"
   130 
   131 instance proof
   132 qed (simp_all add: equal_fun_def fun_eq_iff enum_UNIV)
   133 
   134 end
   135 
   136 lemma [code]:
   137   "HOL.equal f g \<longleftrightarrow> enum_all (%x. f x = g x)"
   138   by (auto simp add: equal fun_eq_iff)
   139 
   140 lemma [code nbe]:
   141   "HOL.equal (f :: _ \<Rightarrow> _) f \<longleftrightarrow> True"
   142   by (fact equal_refl)
   143 
   144 lemma order_fun [code]:
   145   fixes f g :: "'a\<Colon>enum \<Rightarrow> 'b\<Colon>order"
   146   shows "f \<le> g \<longleftrightarrow> enum_all (\<lambda>x. f x \<le> g x)"
   147     and "f < g \<longleftrightarrow> f \<le> g \<and> enum_ex (\<lambda>x. f x \<noteq> g x)"
   148   by (simp_all add: fun_eq_iff le_fun_def order_less_le)
   149 
   150 
   151 subsubsection {* Operations on relations *}
   152 
   153 lemma [code]:
   154   "Id = image (\<lambda>x. (x, x)) (set Enum.enum)"
   155   by (auto intro: imageI in_enum)
   156 
   157 lemma tranclp_unfold [code, no_atp]:
   158   "tranclp r a b \<longleftrightarrow> (a, b) \<in> trancl {(x, y). r x y}"
   159   by (simp add: trancl_def)
   160 
   161 lemma rtranclp_rtrancl_eq [code, no_atp]:
   162   "rtranclp r x y \<longleftrightarrow> (x, y) \<in> rtrancl {(x, y). r x y}"
   163   by (simp add: rtrancl_def)
   164 
   165 lemma max_ext_eq [code]:
   166   "max_ext R = {(X, Y). finite X \<and> finite Y \<and> Y \<noteq> {} \<and> (\<forall>x. x \<in> X \<longrightarrow> (\<exists>xa \<in> Y. (x, xa) \<in> R))}"
   167   by (auto simp add: max_ext.simps)
   168 
   169 lemma max_extp_eq [code]:
   170   "max_extp r x y \<longleftrightarrow> (x, y) \<in> max_ext {(x, y). r x y}"
   171   by (simp add: max_ext_def)
   172 
   173 lemma mlex_eq [code]:
   174   "f <*mlex*> R = {(x, y). f x < f y \<or> (f x \<le> f y \<and> (x, y) \<in> R)}"
   175   by (auto simp add: mlex_prod_def)
   176 
   177 lemma [code]:
   178   fixes xs :: "('a::finite \<times> 'a) list"
   179   shows "acc (set xs) = bacc (set xs) (card_UNIV TYPE('a))"
   180   by (simp add: card_UNIV_def acc_bacc_eq)
   181 
   182 lemma [code]:
   183   "accp r = (\<lambda>x. x \<in> acc {(x, y). r x y})"
   184   by (simp add: acc_def)
   185 
   186 
   187 subsection {* Default instances for @{class enum} *}
   188 
   189 lemma map_of_zip_enum_is_Some:
   190   assumes "length ys = length (enum \<Colon> 'a\<Colon>enum list)"
   191   shows "\<exists>y. map_of (zip (enum \<Colon> 'a\<Colon>enum list) ys) x = Some y"
   192 proof -
   193   from assms have "x \<in> set (enum \<Colon> 'a\<Colon>enum list) \<longleftrightarrow>
   194     (\<exists>y. map_of (zip (enum \<Colon> 'a\<Colon>enum list) ys) x = Some y)"
   195     by (auto intro!: map_of_zip_is_Some)
   196   then show ?thesis using enum_UNIV by auto
   197 qed
   198 
   199 lemma map_of_zip_enum_inject:
   200   fixes xs ys :: "'b\<Colon>enum list"
   201   assumes length: "length xs = length (enum \<Colon> 'a\<Colon>enum list)"
   202       "length ys = length (enum \<Colon> 'a\<Colon>enum list)"
   203     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)"
   204   shows "xs = ys"
   205 proof -
   206   have "map_of (zip (enum \<Colon> 'a list) xs) = map_of (zip (enum \<Colon> 'a list) ys)"
   207   proof
   208     fix x :: 'a
   209     from length map_of_zip_enum_is_Some obtain y1 y2
   210       where "map_of (zip (enum \<Colon> 'a list) xs) x = Some y1"
   211         and "map_of (zip (enum \<Colon> 'a list) ys) x = Some y2" by blast
   212     moreover from map_of
   213       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)"
   214       by (auto dest: fun_cong)
   215     ultimately show "map_of (zip (enum \<Colon> 'a\<Colon>enum list) xs) x = map_of (zip (enum \<Colon> 'a\<Colon>enum list) ys) x"
   216       by simp
   217   qed
   218   with length enum_distinct show "xs = ys" by (rule map_of_zip_inject)
   219 qed
   220 
   221 definition all_n_lists :: "(('a :: enum) list \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> bool"
   222 where
   223   "all_n_lists P n \<longleftrightarrow> (\<forall>xs \<in> set (List.n_lists n enum). P xs)"
   224 
   225 lemma [code]:
   226   "all_n_lists P n \<longleftrightarrow> (if n = 0 then P [] else enum_all (%x. all_n_lists (%xs. P (x # xs)) (n - 1)))"
   227   unfolding all_n_lists_def enum_all
   228   by (cases n) (auto simp add: enum_UNIV)
   229 
   230 definition ex_n_lists :: "(('a :: enum) list \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> bool"
   231 where
   232   "ex_n_lists P n \<longleftrightarrow> (\<exists>xs \<in> set (List.n_lists n enum). P xs)"
   233 
   234 lemma [code]:
   235   "ex_n_lists P n \<longleftrightarrow> (if n = 0 then P [] else enum_ex (%x. ex_n_lists (%xs. P (x # xs)) (n - 1)))"
   236   unfolding ex_n_lists_def enum_ex
   237   by (cases n) (auto simp add: enum_UNIV)
   238 
   239 instantiation "fun" :: (enum, enum) enum
   240 begin
   241 
   242 definition
   243   "enum = map (\<lambda>ys. the o map_of (zip (enum\<Colon>'a list) ys)) (List.n_lists (length (enum\<Colon>'a\<Colon>enum list)) enum)"
   244 
   245 definition
   246   "enum_all P = all_n_lists (\<lambda>bs. P (the o map_of (zip enum bs))) (length (enum :: 'a list))"
   247 
   248 definition
   249   "enum_ex P = ex_n_lists (\<lambda>bs. P (the o map_of (zip enum bs))) (length (enum :: 'a list))"
   250 
   251 instance proof
   252   show "UNIV = set (enum \<Colon> ('a \<Rightarrow> 'b) list)"
   253   proof (rule UNIV_eq_I)
   254     fix f :: "'a \<Rightarrow> 'b"
   255     have "f = the \<circ> map_of (zip (enum \<Colon> 'a\<Colon>enum list) (map f enum))"
   256       by (auto simp add: map_of_zip_map fun_eq_iff intro: in_enum)
   257     then show "f \<in> set enum"
   258       by (auto simp add: enum_fun_def set_n_lists intro: in_enum)
   259   qed
   260 next
   261   from map_of_zip_enum_inject
   262   show "distinct (enum \<Colon> ('a \<Rightarrow> 'b) list)"
   263     by (auto intro!: inj_onI simp add: enum_fun_def
   264       distinct_map distinct_n_lists enum_distinct set_n_lists)
   265 next
   266   fix P
   267   show "enum_all (P :: ('a \<Rightarrow> 'b) \<Rightarrow> bool) = Ball UNIV P"
   268   proof
   269     assume "enum_all P"
   270     show "Ball UNIV P"
   271     proof
   272       fix f :: "'a \<Rightarrow> 'b"
   273       have f: "f = the \<circ> map_of (zip (enum \<Colon> 'a\<Colon>enum list) (map f enum))"
   274         by (auto simp add: map_of_zip_map fun_eq_iff intro: in_enum)
   275       from `enum_all P` have "P (the \<circ> map_of (zip enum (map f enum)))"
   276         unfolding enum_all_fun_def all_n_lists_def
   277         apply (simp add: set_n_lists)
   278         apply (erule_tac x="map f enum" in allE)
   279         apply (auto intro!: in_enum)
   280         done
   281       from this f show "P f" by auto
   282     qed
   283   next
   284     assume "Ball UNIV P"
   285     from this show "enum_all P"
   286       unfolding enum_all_fun_def all_n_lists_def by auto
   287   qed
   288 next
   289   fix P
   290   show "enum_ex (P :: ('a \<Rightarrow> 'b) \<Rightarrow> bool) = Bex UNIV P"
   291   proof
   292     assume "enum_ex P"
   293     from this show "Bex UNIV P"
   294       unfolding enum_ex_fun_def ex_n_lists_def by auto
   295   next
   296     assume "Bex UNIV P"
   297     from this obtain f where "P f" ..
   298     have f: "f = the \<circ> map_of (zip (enum \<Colon> 'a\<Colon>enum list) (map f enum))"
   299       by (auto simp add: map_of_zip_map fun_eq_iff intro: in_enum) 
   300     from `P f` this have "P (the \<circ> map_of (zip (enum \<Colon> 'a\<Colon>enum list) (map f enum)))"
   301       by auto
   302     from  this show "enum_ex P"
   303       unfolding enum_ex_fun_def ex_n_lists_def
   304       apply (auto simp add: set_n_lists)
   305       apply (rule_tac x="map f enum" in exI)
   306       apply (auto intro!: in_enum)
   307       done
   308   qed
   309 qed
   310 
   311 end
   312 
   313 lemma enum_fun_code [code]: "enum = (let enum_a = (enum \<Colon> 'a\<Colon>{enum, equal} list)
   314   in map (\<lambda>ys. the o map_of (zip enum_a ys)) (List.n_lists (length enum_a) enum))"
   315   by (simp add: enum_fun_def Let_def)
   316 
   317 lemma enum_all_fun_code [code]:
   318   "enum_all P = (let enum_a = (enum :: 'a::{enum, equal} list)
   319    in all_n_lists (\<lambda>bs. P (the o map_of (zip enum_a bs))) (length enum_a))"
   320   by (simp only: enum_all_fun_def Let_def)
   321 
   322 lemma enum_ex_fun_code [code]:
   323   "enum_ex P = (let enum_a = (enum :: 'a::{enum, equal} list)
   324    in ex_n_lists (\<lambda>bs. P (the o map_of (zip enum_a bs))) (length enum_a))"
   325   by (simp only: enum_ex_fun_def Let_def)
   326 
   327 instantiation set :: (enum) enum
   328 begin
   329 
   330 definition
   331   "enum = map set (sublists enum)"
   332 
   333 definition
   334   "enum_all P \<longleftrightarrow> (\<forall>A\<in>set enum. P (A::'a set))"
   335 
   336 definition
   337   "enum_ex P \<longleftrightarrow> (\<exists>A\<in>set enum. P (A::'a set))"
   338 
   339 instance proof
   340 qed (simp_all add: enum_set_def enum_all_set_def enum_ex_set_def sublists_powset distinct_set_sublists
   341   enum_distinct enum_UNIV)
   342 
   343 end
   344 
   345 instantiation unit :: enum
   346 begin
   347 
   348 definition
   349   "enum = [()]"
   350 
   351 definition
   352   "enum_all P = P ()"
   353 
   354 definition
   355   "enum_ex P = P ()"
   356 
   357 instance proof
   358 qed (auto simp add: enum_unit_def enum_all_unit_def enum_ex_unit_def)
   359 
   360 end
   361 
   362 instantiation bool :: enum
   363 begin
   364 
   365 definition
   366   "enum = [False, True]"
   367 
   368 definition
   369   "enum_all P \<longleftrightarrow> P False \<and> P True"
   370 
   371 definition
   372   "enum_ex P \<longleftrightarrow> P False \<or> P True"
   373 
   374 instance proof
   375 qed (simp_all only: enum_bool_def enum_all_bool_def enum_ex_bool_def UNIV_bool, simp_all)
   376 
   377 end
   378 
   379 instantiation prod :: (enum, enum) enum
   380 begin
   381 
   382 definition
   383   "enum = List.product enum enum"
   384 
   385 definition
   386   "enum_all P = enum_all (%x. enum_all (%y. P (x, y)))"
   387 
   388 definition
   389   "enum_ex P = enum_ex (%x. enum_ex (%y. P (x, y)))"
   390 
   391  
   392 instance by default
   393   (simp_all add: enum_prod_def product_list_set distinct_product
   394     enum_UNIV enum_distinct enum_all_prod_def enum_ex_prod_def)
   395 
   396 end
   397 
   398 instantiation sum :: (enum, enum) enum
   399 begin
   400 
   401 definition
   402   "enum = map Inl enum @ map Inr enum"
   403 
   404 definition
   405   "enum_all P \<longleftrightarrow> enum_all (\<lambda>x. P (Inl x)) \<and> enum_all (\<lambda>x. P (Inr x))"
   406 
   407 definition
   408   "enum_ex P \<longleftrightarrow> enum_ex (\<lambda>x. P (Inl x)) \<or> enum_ex (\<lambda>x. P (Inr x))"
   409 
   410 instance proof
   411 qed (simp_all only: enum_sum_def enum_all_sum_def enum_ex_sum_def UNIV_sum,
   412   auto simp add: enum_UNIV distinct_map enum_distinct)
   413 
   414 end
   415 
   416 instantiation option :: (enum) enum
   417 begin
   418 
   419 definition
   420   "enum = None # map Some enum"
   421 
   422 definition
   423   "enum_all P \<longleftrightarrow> P None \<and> enum_all (\<lambda>x. P (Some x))"
   424 
   425 definition
   426   "enum_ex P \<longleftrightarrow> P None \<or> enum_ex (\<lambda>x. P (Some x))"
   427 
   428 instance proof
   429 qed (simp_all only: enum_option_def enum_all_option_def enum_ex_option_def UNIV_option_conv,
   430   auto simp add: distinct_map enum_UNIV enum_distinct)
   431 
   432 end
   433 
   434 
   435 subsection {* Small finite types *}
   436 
   437 text {* We define small finite types for the use in Quickcheck *}
   438 
   439 datatype finite_1 = a\<^isub>1
   440 
   441 notation (output) a\<^isub>1  ("a\<^isub>1")
   442 
   443 lemma UNIV_finite_1:
   444   "UNIV = {a\<^isub>1}"
   445   by (auto intro: finite_1.exhaust)
   446 
   447 instantiation finite_1 :: enum
   448 begin
   449 
   450 definition
   451   "enum = [a\<^isub>1]"
   452 
   453 definition
   454   "enum_all P = P a\<^isub>1"
   455 
   456 definition
   457   "enum_ex P = P a\<^isub>1"
   458 
   459 instance proof
   460 qed (simp_all only: enum_finite_1_def enum_all_finite_1_def enum_ex_finite_1_def UNIV_finite_1, simp_all)
   461 
   462 end
   463 
   464 instantiation finite_1 :: linorder
   465 begin
   466 
   467 definition less_finite_1 :: "finite_1 \<Rightarrow> finite_1 \<Rightarrow> bool"
   468 where
   469   "x < (y :: finite_1) \<longleftrightarrow> False"
   470 
   471 definition less_eq_finite_1 :: "finite_1 \<Rightarrow> finite_1 \<Rightarrow> bool"
   472 where
   473   "x \<le> (y :: finite_1) \<longleftrightarrow> True"
   474 
   475 instance
   476 apply (intro_classes)
   477 apply (auto simp add: less_finite_1_def less_eq_finite_1_def)
   478 apply (metis finite_1.exhaust)
   479 done
   480 
   481 end
   482 
   483 hide_const (open) a\<^isub>1
   484 
   485 datatype finite_2 = a\<^isub>1 | a\<^isub>2
   486 
   487 notation (output) a\<^isub>1  ("a\<^isub>1")
   488 notation (output) a\<^isub>2  ("a\<^isub>2")
   489 
   490 lemma UNIV_finite_2:
   491   "UNIV = {a\<^isub>1, a\<^isub>2}"
   492   by (auto intro: finite_2.exhaust)
   493 
   494 instantiation finite_2 :: enum
   495 begin
   496 
   497 definition
   498   "enum = [a\<^isub>1, a\<^isub>2]"
   499 
   500 definition
   501   "enum_all P \<longleftrightarrow> P a\<^isub>1 \<and> P a\<^isub>2"
   502 
   503 definition
   504   "enum_ex P \<longleftrightarrow> P a\<^isub>1 \<or> P a\<^isub>2"
   505 
   506 instance proof
   507 qed (simp_all only: enum_finite_2_def enum_all_finite_2_def enum_ex_finite_2_def UNIV_finite_2, simp_all)
   508 
   509 end
   510 
   511 instantiation finite_2 :: linorder
   512 begin
   513 
   514 definition less_finite_2 :: "finite_2 \<Rightarrow> finite_2 \<Rightarrow> bool"
   515 where
   516   "x < y \<longleftrightarrow> x = a\<^isub>1 \<and> y = a\<^isub>2"
   517 
   518 definition less_eq_finite_2 :: "finite_2 \<Rightarrow> finite_2 \<Rightarrow> bool"
   519 where
   520   "x \<le> y \<longleftrightarrow> x = y \<or> x < (y :: finite_2)"
   521 
   522 instance
   523 apply (intro_classes)
   524 apply (auto simp add: less_finite_2_def less_eq_finite_2_def)
   525 apply (metis finite_2.nchotomy)+
   526 done
   527 
   528 end
   529 
   530 hide_const (open) a\<^isub>1 a\<^isub>2
   531 
   532 datatype finite_3 = a\<^isub>1 | a\<^isub>2 | a\<^isub>3
   533 
   534 notation (output) a\<^isub>1  ("a\<^isub>1")
   535 notation (output) a\<^isub>2  ("a\<^isub>2")
   536 notation (output) a\<^isub>3  ("a\<^isub>3")
   537 
   538 lemma UNIV_finite_3:
   539   "UNIV = {a\<^isub>1, a\<^isub>2, a\<^isub>3}"
   540   by (auto intro: finite_3.exhaust)
   541 
   542 instantiation finite_3 :: enum
   543 begin
   544 
   545 definition
   546   "enum = [a\<^isub>1, a\<^isub>2, a\<^isub>3]"
   547 
   548 definition
   549   "enum_all P \<longleftrightarrow> P a\<^isub>1 \<and> P a\<^isub>2 \<and> P a\<^isub>3"
   550 
   551 definition
   552   "enum_ex P \<longleftrightarrow> P a\<^isub>1 \<or> P a\<^isub>2 \<or> P a\<^isub>3"
   553 
   554 instance proof
   555 qed (simp_all only: enum_finite_3_def enum_all_finite_3_def enum_ex_finite_3_def UNIV_finite_3, simp_all)
   556 
   557 end
   558 
   559 instantiation finite_3 :: linorder
   560 begin
   561 
   562 definition less_finite_3 :: "finite_3 \<Rightarrow> finite_3 \<Rightarrow> bool"
   563 where
   564   "x < y = (case x of a\<^isub>1 \<Rightarrow> y \<noteq> a\<^isub>1 | a\<^isub>2 \<Rightarrow> y = a\<^isub>3 | a\<^isub>3 \<Rightarrow> False)"
   565 
   566 definition less_eq_finite_3 :: "finite_3 \<Rightarrow> finite_3 \<Rightarrow> bool"
   567 where
   568   "x \<le> y \<longleftrightarrow> x = y \<or> x < (y :: finite_3)"
   569 
   570 instance proof (intro_classes)
   571 qed (auto simp add: less_finite_3_def less_eq_finite_3_def split: finite_3.split_asm)
   572 
   573 end
   574 
   575 hide_const (open) a\<^isub>1 a\<^isub>2 a\<^isub>3
   576 
   577 datatype finite_4 = a\<^isub>1 | a\<^isub>2 | a\<^isub>3 | a\<^isub>4
   578 
   579 notation (output) a\<^isub>1  ("a\<^isub>1")
   580 notation (output) a\<^isub>2  ("a\<^isub>2")
   581 notation (output) a\<^isub>3  ("a\<^isub>3")
   582 notation (output) a\<^isub>4  ("a\<^isub>4")
   583 
   584 lemma UNIV_finite_4:
   585   "UNIV = {a\<^isub>1, a\<^isub>2, a\<^isub>3, a\<^isub>4}"
   586   by (auto intro: finite_4.exhaust)
   587 
   588 instantiation finite_4 :: enum
   589 begin
   590 
   591 definition
   592   "enum = [a\<^isub>1, a\<^isub>2, a\<^isub>3, a\<^isub>4]"
   593 
   594 definition
   595   "enum_all P \<longleftrightarrow> P a\<^isub>1 \<and> P a\<^isub>2 \<and> P a\<^isub>3 \<and> P a\<^isub>4"
   596 
   597 definition
   598   "enum_ex P \<longleftrightarrow> P a\<^isub>1 \<or> P a\<^isub>2 \<or> P a\<^isub>3 \<or> P a\<^isub>4"
   599 
   600 instance proof
   601 qed (simp_all only: enum_finite_4_def enum_all_finite_4_def enum_ex_finite_4_def UNIV_finite_4, simp_all)
   602 
   603 end
   604 
   605 hide_const (open) a\<^isub>1 a\<^isub>2 a\<^isub>3 a\<^isub>4
   606 
   607 
   608 datatype finite_5 = a\<^isub>1 | a\<^isub>2 | a\<^isub>3 | a\<^isub>4 | a\<^isub>5
   609 
   610 notation (output) a\<^isub>1  ("a\<^isub>1")
   611 notation (output) a\<^isub>2  ("a\<^isub>2")
   612 notation (output) a\<^isub>3  ("a\<^isub>3")
   613 notation (output) a\<^isub>4  ("a\<^isub>4")
   614 notation (output) a\<^isub>5  ("a\<^isub>5")
   615 
   616 lemma UNIV_finite_5:
   617   "UNIV = {a\<^isub>1, a\<^isub>2, a\<^isub>3, a\<^isub>4, a\<^isub>5}"
   618   by (auto intro: finite_5.exhaust)
   619 
   620 instantiation finite_5 :: enum
   621 begin
   622 
   623 definition
   624   "enum = [a\<^isub>1, a\<^isub>2, a\<^isub>3, a\<^isub>4, a\<^isub>5]"
   625 
   626 definition
   627   "enum_all P \<longleftrightarrow> P a\<^isub>1 \<and> P a\<^isub>2 \<and> P a\<^isub>3 \<and> P a\<^isub>4 \<and> P a\<^isub>5"
   628 
   629 definition
   630   "enum_ex P \<longleftrightarrow> P a\<^isub>1 \<or> P a\<^isub>2 \<or> P a\<^isub>3 \<or> P a\<^isub>4 \<or> P a\<^isub>5"
   631 
   632 instance proof
   633 qed (simp_all only: enum_finite_5_def enum_all_finite_5_def enum_ex_finite_5_def UNIV_finite_5, simp_all)
   634 
   635 end
   636 
   637 hide_const (open) a\<^isub>1 a\<^isub>2 a\<^isub>3 a\<^isub>4 a\<^isub>5
   638 
   639 
   640 subsection {* Closing up *}
   641 
   642 hide_type (open) finite_1 finite_2 finite_3 finite_4 finite_5
   643 hide_const (open) enum enum_all enum_ex all_n_lists ex_n_lists ntrancl
   644 
   645 end
   646