src/HOL/ex/CodeCollections.thy
changeset 21460 cda5cd8bfd16
parent 21404 eb85850d3eb7
child 21545 54cc492d80a9
equal deleted inserted replaced
21459:20c2ddee8bc5 21460:cda5cd8bfd16
     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
   367 
   168 
   368 primrec
   169 primrec
   369   "get_index p n [] = None"
   170   "get_index p n [] = None"
   370   "get_index p n (x#xs) = (if p x then Some n else get_index p (Suc n) xs)"
   171   "get_index p n (x#xs) = (if p x then Some n else get_index p (Suc n) xs)"
   371 
   172 
   372 definition
   173 (*definition
   373   between :: "'a::enum \<Rightarrow> 'a \<Rightarrow> 'a option" where
   174   between :: "'a::enum \<Rightarrow> 'a \<Rightarrow> 'a option" where
   374   "between x y = get_first (\<lambda>z. x << z & z << y) enum"
   175   "between x y = get_first (\<lambda>z. x << z & z << y) enum"
   375 
   176 
   376 definition
   177 definition
   377   index :: "'a::enum \<Rightarrow> nat" where
   178   index :: "'a::enum \<Rightarrow> nat" where
   387 consts
   188 consts
   388   sum :: "'a::{enum, infimum} list \<Rightarrow> 'a"
   189   sum :: "'a::{enum, infimum} list \<Rightarrow> 'a"
   389 
   190 
   390 primrec
   191 primrec
   391   "sum [] = inf"
   192   "sum [] = inf"
   392   "sum (x#xs) = add x (sum xs)"
   193   "sum (x#xs) = add x (sum xs)"*)
   393 
   194 
   394 definition "test1 = sum [None, Some True, None, Some False]"
   195 (*definition "test1 = sum [None, Some True, None, Some False]"*)
   395 definition "test2 = (inf :: nat \<times> unit)"
   196 (*definition "test2 = (inf :: nat \<times> unit)"*)
   396 
   197 definition "test3 \<longleftrightarrow> (\<exists>x \<Colon> bool option. case x of Some P \<Rightarrow> P | None \<Rightarrow> False)"
   397 code_gen "op <<="
   198 
   398 code_gen "op <<"
   199 code_gen test3
   399 code_gen inf
       
   400 code_gen between
       
   401 code_gen index
       
   402 code_gen test1
       
   403 code_gen test2
       
   404 
   200 
   405 code_gen (SML *)
   201 code_gen (SML *)
   406 code_gen (Haskell -)
   202 code_gen (Haskell -)
   407 
   203 
   408 end
   204 end