src/HOL/Library/Mapping.thy
author wenzelm
Sun Nov 02 17:20:45 2014 +0100 (2014-11-02)
changeset 58881 b9556a055632
parent 56545 8f1e7596deb7
child 59485 792272e6ee6b
permissions -rw-r--r--
modernized header;
     1 (*  Title:      HOL/Library/Mapping.thy
     2     Author:     Florian Haftmann and Ondrej Kuncar
     3 *)
     4 
     5 section {* An abstract view on maps for code generation. *}
     6 
     7 theory Mapping
     8 imports Main
     9 begin
    10 
    11 subsection {* Parametricity transfer rules *}
    12 
    13 lemma map_of_foldr: -- {* FIXME move *}
    14   "map_of xs = foldr (\<lambda>(k, v) m. m(k \<mapsto> v)) xs Map.empty"
    15   using map_add_map_of_foldr [of Map.empty] by auto
    16 
    17 context
    18 begin
    19 
    20 interpretation lifting_syntax .
    21 
    22 lemma empty_parametric:
    23   "(A ===> rel_option B) Map.empty Map.empty"
    24   by transfer_prover
    25 
    26 lemma lookup_parametric: "((A ===> B) ===> A ===> B) (\<lambda>m k. m k) (\<lambda>m k. m k)"
    27   by transfer_prover
    28 
    29 lemma update_parametric:
    30   assumes [transfer_rule]: "bi_unique A"
    31   shows "(A ===> B ===> (A ===> rel_option B) ===> A ===> rel_option B)
    32     (\<lambda>k v m. m(k \<mapsto> v)) (\<lambda>k v m. m(k \<mapsto> v))"
    33   by transfer_prover
    34 
    35 lemma delete_parametric:
    36   assumes [transfer_rule]: "bi_unique A"
    37   shows "(A ===> (A ===> rel_option B) ===> A ===> rel_option B) 
    38     (\<lambda>k m. m(k := None)) (\<lambda>k m. m(k := None))"
    39   by transfer_prover
    40 
    41 lemma is_none_parametric [transfer_rule]:
    42   "(rel_option A ===> HOL.eq) Option.is_none Option.is_none"
    43   by (auto simp add: is_none_def rel_fun_def rel_option_iff split: option.split)
    44 
    45 lemma dom_parametric:
    46   assumes [transfer_rule]: "bi_total A"
    47   shows "((A ===> rel_option B) ===> rel_set A) dom dom" 
    48   unfolding dom_def [abs_def] is_none_def [symmetric] by transfer_prover
    49 
    50 lemma map_of_parametric [transfer_rule]:
    51   assumes [transfer_rule]: "bi_unique R1"
    52   shows "(list_all2 (rel_prod R1 R2) ===> R1 ===> rel_option R2) map_of map_of"
    53   unfolding map_of_def by transfer_prover
    54 
    55 lemma map_entry_parametric [transfer_rule]:
    56   assumes [transfer_rule]: "bi_unique A"
    57   shows "(A ===> (B ===> B) ===> (A ===> rel_option B) ===> A ===> rel_option B) 
    58     (\<lambda>k f m. (case m k of None \<Rightarrow> m
    59       | Some v \<Rightarrow> m (k \<mapsto> (f v)))) (\<lambda>k f m. (case m k of None \<Rightarrow> m
    60       | Some v \<Rightarrow> m (k \<mapsto> (f v))))"
    61   by transfer_prover
    62 
    63 lemma tabulate_parametric: 
    64   assumes [transfer_rule]: "bi_unique A"
    65   shows "(list_all2 A ===> (A ===> B) ===> A ===> rel_option B) 
    66     (\<lambda>ks f. (map_of (map (\<lambda>k. (k, f k)) ks))) (\<lambda>ks f. (map_of (map (\<lambda>k. (k, f k)) ks)))"
    67   by transfer_prover
    68 
    69 lemma bulkload_parametric: 
    70   "(list_all2 A ===> HOL.eq ===> rel_option A) 
    71     (\<lambda>xs k. if k < length xs then Some (xs ! k) else None) (\<lambda>xs k. if k < length xs then Some (xs ! k) else None)"
    72 proof
    73   fix xs ys
    74   assume "list_all2 A xs ys"
    75   then show "(HOL.eq ===> rel_option A)
    76     (\<lambda>k. if k < length xs then Some (xs ! k) else None)
    77     (\<lambda>k. if k < length ys then Some (ys ! k) else None)"
    78     apply induct
    79     apply auto
    80     unfolding rel_fun_def
    81     apply clarsimp 
    82     apply (case_tac xa) 
    83     apply (auto dest: list_all2_lengthD list_all2_nthD)
    84     done
    85 qed
    86 
    87 lemma map_parametric: 
    88   "((A ===> B) ===> (C ===> D) ===> (B ===> rel_option C) ===> A ===> rel_option D) 
    89      (\<lambda>f g m. (map_option g \<circ> m \<circ> f)) (\<lambda>f g m. (map_option g \<circ> m \<circ> f))"
    90   by transfer_prover
    91 
    92 end
    93 
    94 
    95 subsection {* Type definition and primitive operations *}
    96 
    97 typedef ('a, 'b) mapping = "UNIV :: ('a \<rightharpoonup> 'b) set"
    98   morphisms rep Mapping
    99   ..
   100 
   101 setup_lifting (no_code) type_definition_mapping
   102 
   103 lift_definition empty :: "('a, 'b) mapping"
   104   is Map.empty parametric empty_parametric .
   105 
   106 lift_definition lookup :: "('a, 'b) mapping \<Rightarrow> 'a \<Rightarrow> 'b option"
   107   is "\<lambda>m k. m k" parametric lookup_parametric .
   108 
   109 lift_definition update :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   110   is "\<lambda>k v m. m(k \<mapsto> v)" parametric update_parametric .
   111 
   112 lift_definition delete :: "'a \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   113   is "\<lambda>k m. m(k := None)" parametric delete_parametric .
   114 
   115 lift_definition keys :: "('a, 'b) mapping \<Rightarrow> 'a set"
   116   is dom parametric dom_parametric .
   117 
   118 lift_definition tabulate :: "'a list \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping"
   119   is "\<lambda>ks f. (map_of (List.map (\<lambda>k. (k, f k)) ks))" parametric tabulate_parametric .
   120 
   121 lift_definition bulkload :: "'a list \<Rightarrow> (nat, 'a) mapping"
   122   is "\<lambda>xs k. if k < length xs then Some (xs ! k) else None" parametric bulkload_parametric .
   123 
   124 lift_definition map :: "('c \<Rightarrow> 'a) \<Rightarrow> ('b \<Rightarrow> 'd) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('c, 'd) mapping"
   125   is "\<lambda>f g m. (map_option g \<circ> m \<circ> f)" parametric map_parametric .
   126 
   127 
   128 subsection {* Functorial structure *}
   129 
   130 functor map: map
   131   by (transfer, auto simp add: fun_eq_iff option.map_comp option.map_id)+
   132 
   133 
   134 subsection {* Derived operations *}
   135 
   136 definition ordered_keys :: "('a\<Colon>linorder, 'b) mapping \<Rightarrow> 'a list"
   137 where
   138   "ordered_keys m = (if finite (keys m) then sorted_list_of_set (keys m) else [])"
   139 
   140 definition is_empty :: "('a, 'b) mapping \<Rightarrow> bool"
   141 where
   142   "is_empty m \<longleftrightarrow> keys m = {}"
   143 
   144 definition size :: "('a, 'b) mapping \<Rightarrow> nat"
   145 where
   146   "size m = (if finite (keys m) then card (keys m) else 0)"
   147 
   148 definition replace :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   149 where
   150   "replace k v m = (if k \<in> keys m then update k v m else m)"
   151 
   152 definition default :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   153 where
   154   "default k v m = (if k \<in> keys m then m else update k v m)"
   155 
   156 text {* Manual derivation of transfer rule is non-trivial *}
   157 
   158 lift_definition map_entry :: "'a \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" is
   159   "\<lambda>k f m. (case m k of None \<Rightarrow> m
   160     | Some v \<Rightarrow> m (k \<mapsto> (f v)))" parametric map_entry_parametric .
   161 
   162 lemma map_entry_code [code]:
   163   "map_entry k f m = (case lookup m k of None \<Rightarrow> m
   164     | Some v \<Rightarrow> update k (f v) m)"
   165   by transfer rule
   166 
   167 definition map_default :: "'a \<Rightarrow> 'b \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   168 where
   169   "map_default k v f m = map_entry k f (default k v m)" 
   170 
   171 definition of_alist :: "('k \<times> 'v) list \<Rightarrow> ('k, 'v) mapping"
   172 where
   173   "of_alist xs = foldr (\<lambda>(k, v) m. update k v m) xs empty"
   174 
   175 instantiation mapping :: (type, type) equal
   176 begin
   177 
   178 definition
   179   "HOL.equal m1 m2 \<longleftrightarrow> (\<forall>k. lookup m1 k = lookup m2 k)"
   180 
   181 instance proof
   182 qed (unfold equal_mapping_def, transfer, auto)
   183 
   184 end
   185 
   186 context
   187 begin
   188 
   189 interpretation lifting_syntax .
   190 
   191 lemma [transfer_rule]:
   192   assumes [transfer_rule]: "bi_total A"
   193   assumes [transfer_rule]: "bi_unique B"
   194   shows "(pcr_mapping A B ===> pcr_mapping A B ===> op=) HOL.eq HOL.equal"
   195   by (unfold equal) transfer_prover
   196 
   197 lemma of_alist_transfer [transfer_rule]:
   198   assumes [transfer_rule]: "bi_unique R1"
   199   shows "(list_all2 (rel_prod R1 R2) ===> pcr_mapping R1 R2) map_of of_alist"
   200   unfolding of_alist_def [abs_def] map_of_foldr [abs_def] by transfer_prover
   201 
   202 end
   203 
   204 
   205 subsection {* Properties *}
   206 
   207 lemma lookup_update:
   208   "lookup (update k v m) k = Some v" 
   209   by transfer simp
   210 
   211 lemma lookup_update_neq:
   212   "k \<noteq> k' \<Longrightarrow> lookup (update k v m) k' = lookup m k'" 
   213   by transfer simp
   214 
   215 lemma lookup_empty:
   216   "lookup empty k = None" 
   217   by transfer simp
   218 
   219 lemma keys_is_none_rep [code_unfold]:
   220   "k \<in> keys m \<longleftrightarrow> \<not> (Option.is_none (lookup m k))"
   221   by transfer (auto simp add: is_none_def)
   222 
   223 lemma update_update:
   224   "update k v (update k w m) = update k v m"
   225   "k \<noteq> l \<Longrightarrow> update k v (update l w m) = update l w (update k v m)"
   226   by (transfer, simp add: fun_upd_twist)+
   227 
   228 lemma update_delete [simp]:
   229   "update k v (delete k m) = update k v m"
   230   by transfer simp
   231 
   232 lemma delete_update:
   233   "delete k (update k v m) = delete k m"
   234   "k \<noteq> l \<Longrightarrow> delete k (update l v m) = update l v (delete k m)"
   235   by (transfer, simp add: fun_upd_twist)+
   236 
   237 lemma delete_empty [simp]:
   238   "delete k empty = empty"
   239   by transfer simp
   240 
   241 lemma replace_update:
   242   "k \<notin> keys m \<Longrightarrow> replace k v m = m"
   243   "k \<in> keys m \<Longrightarrow> replace k v m = update k v m"
   244   by (transfer, auto simp add: replace_def fun_upd_twist)+
   245 
   246 lemma size_empty [simp]:
   247   "size empty = 0"
   248   unfolding size_def by transfer simp
   249 
   250 lemma size_update:
   251   "finite (keys m) \<Longrightarrow> size (update k v m) =
   252     (if k \<in> keys m then size m else Suc (size m))"
   253   unfolding size_def by transfer (auto simp add: insert_dom)
   254 
   255 lemma size_delete:
   256   "size (delete k m) = (if k \<in> keys m then size m - 1 else size m)"
   257   unfolding size_def by transfer simp
   258 
   259 lemma size_tabulate [simp]:
   260   "size (tabulate ks f) = length (remdups ks)"
   261   unfolding size_def by transfer (auto simp add: map_of_map_restrict  card_set comp_def)
   262 
   263 lemma bulkload_tabulate:
   264   "bulkload xs = tabulate [0..<length xs] (nth xs)"
   265   by transfer (auto simp add: map_of_map_restrict)
   266 
   267 lemma is_empty_empty [simp]:
   268   "is_empty empty"
   269   unfolding is_empty_def by transfer simp 
   270 
   271 lemma is_empty_update [simp]:
   272   "\<not> is_empty (update k v m)"
   273   unfolding is_empty_def by transfer simp
   274 
   275 lemma is_empty_delete:
   276   "is_empty (delete k m) \<longleftrightarrow> is_empty m \<or> keys m = {k}"
   277   unfolding is_empty_def by transfer (auto simp del: dom_eq_empty_conv)
   278 
   279 lemma is_empty_replace [simp]:
   280   "is_empty (replace k v m) \<longleftrightarrow> is_empty m"
   281   unfolding is_empty_def replace_def by transfer auto
   282 
   283 lemma is_empty_default [simp]:
   284   "\<not> is_empty (default k v m)"
   285   unfolding is_empty_def default_def by transfer auto
   286 
   287 lemma is_empty_map_entry [simp]:
   288   "is_empty (map_entry k f m) \<longleftrightarrow> is_empty m"
   289   unfolding is_empty_def by transfer (auto split: option.split)
   290 
   291 lemma is_empty_map_default [simp]:
   292   "\<not> is_empty (map_default k v f m)"
   293   by (simp add: map_default_def)
   294 
   295 lemma keys_dom_lookup:
   296   "keys m = dom (Mapping.lookup m)"
   297   by transfer rule
   298 
   299 lemma keys_empty [simp]:
   300   "keys empty = {}"
   301   by transfer simp
   302 
   303 lemma keys_update [simp]:
   304   "keys (update k v m) = insert k (keys m)"
   305   by transfer simp
   306 
   307 lemma keys_delete [simp]:
   308   "keys (delete k m) = keys m - {k}"
   309   by transfer simp
   310 
   311 lemma keys_replace [simp]:
   312   "keys (replace k v m) = keys m"
   313   unfolding replace_def by transfer (simp add: insert_absorb)
   314 
   315 lemma keys_default [simp]:
   316   "keys (default k v m) = insert k (keys m)"
   317   unfolding default_def by transfer (simp add: insert_absorb)
   318 
   319 lemma keys_map_entry [simp]:
   320   "keys (map_entry k f m) = keys m"
   321   by transfer (auto split: option.split)
   322 
   323 lemma keys_map_default [simp]:
   324   "keys (map_default k v f m) = insert k (keys m)"
   325   by (simp add: map_default_def)
   326 
   327 lemma keys_tabulate [simp]:
   328   "keys (tabulate ks f) = set ks"
   329   by transfer (simp add: map_of_map_restrict o_def)
   330 
   331 lemma keys_bulkload [simp]:
   332   "keys (bulkload xs) = {0..<length xs}"
   333   by (simp add: bulkload_tabulate)
   334 
   335 lemma distinct_ordered_keys [simp]:
   336   "distinct (ordered_keys m)"
   337   by (simp add: ordered_keys_def)
   338 
   339 lemma ordered_keys_infinite [simp]:
   340   "\<not> finite (keys m) \<Longrightarrow> ordered_keys m = []"
   341   by (simp add: ordered_keys_def)
   342 
   343 lemma ordered_keys_empty [simp]:
   344   "ordered_keys empty = []"
   345   by (simp add: ordered_keys_def)
   346 
   347 lemma ordered_keys_update [simp]:
   348   "k \<in> keys m \<Longrightarrow> ordered_keys (update k v m) = ordered_keys m"
   349   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (update k v m) = insort k (ordered_keys m)"
   350   by (simp_all add: ordered_keys_def) (auto simp only: sorted_list_of_set_insert [symmetric] insert_absorb)
   351 
   352 lemma ordered_keys_delete [simp]:
   353   "ordered_keys (delete k m) = remove1 k (ordered_keys m)"
   354 proof (cases "finite (keys m)")
   355   case False then show ?thesis by simp
   356 next
   357   case True note fin = True
   358   show ?thesis
   359   proof (cases "k \<in> keys m")
   360     case False with fin have "k \<notin> set (sorted_list_of_set (keys m))" by simp
   361     with False show ?thesis by (simp add: ordered_keys_def remove1_idem)
   362   next
   363     case True with fin show ?thesis by (simp add: ordered_keys_def sorted_list_of_set_remove)
   364   qed
   365 qed
   366 
   367 lemma ordered_keys_replace [simp]:
   368   "ordered_keys (replace k v m) = ordered_keys m"
   369   by (simp add: replace_def)
   370 
   371 lemma ordered_keys_default [simp]:
   372   "k \<in> keys m \<Longrightarrow> ordered_keys (default k v m) = ordered_keys m"
   373   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (default k v m) = insort k (ordered_keys m)"
   374   by (simp_all add: default_def)
   375 
   376 lemma ordered_keys_map_entry [simp]:
   377   "ordered_keys (map_entry k f m) = ordered_keys m"
   378   by (simp add: ordered_keys_def)
   379 
   380 lemma ordered_keys_map_default [simp]:
   381   "k \<in> keys m \<Longrightarrow> ordered_keys (map_default k v f m) = ordered_keys m"
   382   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (map_default k v f m) = insort k (ordered_keys m)"
   383   by (simp_all add: map_default_def)
   384 
   385 lemma ordered_keys_tabulate [simp]:
   386   "ordered_keys (tabulate ks f) = sort (remdups ks)"
   387   by (simp add: ordered_keys_def sorted_list_of_set_sort_remdups)
   388 
   389 lemma ordered_keys_bulkload [simp]:
   390   "ordered_keys (bulkload ks) = [0..<length ks]"
   391   by (simp add: ordered_keys_def)
   392 
   393 lemma tabulate_fold:
   394   "tabulate xs f = fold (\<lambda>k m. update k (f k) m) xs empty"
   395 proof transfer
   396   fix f :: "'a \<Rightarrow> 'b" and xs
   397   have "map_of (List.map (\<lambda>k. (k, f k)) xs) = foldr (\<lambda>k m. m(k \<mapsto> f k)) xs Map.empty"
   398     by (simp add: foldr_map comp_def map_of_foldr)
   399   also have "foldr (\<lambda>k m. m(k \<mapsto> f k)) xs = fold (\<lambda>k m. m(k \<mapsto> f k)) xs"
   400     by (rule foldr_fold) (simp add: fun_eq_iff)
   401   ultimately show "map_of (List.map (\<lambda>k. (k, f k)) xs) = fold (\<lambda>k m. m(k \<mapsto> f k)) xs Map.empty"
   402     by simp
   403 qed
   404 
   405 
   406 subsection {* Code generator setup *}
   407 
   408 code_datatype empty update
   409 
   410 hide_const (open) empty is_empty rep lookup update delete ordered_keys keys size
   411   replace default map_entry map_default tabulate bulkload map of_alist
   412 
   413 end