src/HOL/Library/Mapping.thy
author wenzelm
Mon Dec 28 01:28:28 2015 +0100 (2015-12-28)
changeset 61945 1135b8de26c3
parent 61585 a9599d3d7610
child 63194 0b7bdb75f451
permissions -rw-r--r--
more symbols;
     1 (*  Title:      HOL/Library/Mapping.thy
     2     Author:     Florian Haftmann and Ondrej Kuncar
     3 *)
     4 
     5 section \<open>An abstract view on maps for code generation.\<close>
     6 
     7 theory Mapping
     8 imports Main
     9 begin
    10 
    11 subsection \<open>Parametricity transfer rules\<close>
    12 
    13 lemma map_of_foldr: \<comment> \<open>FIXME move\<close>
    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: Option.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] Option.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 \<open>Type definition and primitive operations\<close>
    96 
    97 typedef ('a, 'b) mapping = "UNIV :: ('a \<rightharpoonup> 'b) set"
    98   morphisms rep Mapping
    99   ..
   100 
   101 setup_lifting 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 declare [[code drop: Mapping.lookup]]
   110 setup \<open>Code.add_default_eqn @{thm Mapping.lookup.abs_eq}\<close> \<comment> \<open>FIXME lifting\<close>
   111 
   112 lift_definition update :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   113   is "\<lambda>k v m. m(k \<mapsto> v)" parametric update_parametric .
   114 
   115 lift_definition delete :: "'a \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   116   is "\<lambda>k m. m(k := None)" parametric delete_parametric .
   117 
   118 lift_definition keys :: "('a, 'b) mapping \<Rightarrow> 'a set"
   119   is dom parametric dom_parametric .
   120 
   121 lift_definition tabulate :: "'a list \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping"
   122   is "\<lambda>ks f. (map_of (List.map (\<lambda>k. (k, f k)) ks))" parametric tabulate_parametric .
   123 
   124 lift_definition bulkload :: "'a list \<Rightarrow> (nat, 'a) mapping"
   125   is "\<lambda>xs k. if k < length xs then Some (xs ! k) else None" parametric bulkload_parametric .
   126 
   127 lift_definition map :: "('c \<Rightarrow> 'a) \<Rightarrow> ('b \<Rightarrow> 'd) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('c, 'd) mapping"
   128   is "\<lambda>f g m. (map_option g \<circ> m \<circ> f)" parametric map_parametric .
   129 
   130 declare [[code drop: map]]
   131 
   132 
   133 subsection \<open>Functorial structure\<close>
   134 
   135 functor map: map
   136   by (transfer, auto simp add: fun_eq_iff option.map_comp option.map_id)+
   137 
   138 
   139 subsection \<open>Derived operations\<close>
   140 
   141 definition ordered_keys :: "('a::linorder, 'b) mapping \<Rightarrow> 'a list"
   142 where
   143   "ordered_keys m = (if finite (keys m) then sorted_list_of_set (keys m) else [])"
   144 
   145 definition is_empty :: "('a, 'b) mapping \<Rightarrow> bool"
   146 where
   147   "is_empty m \<longleftrightarrow> keys m = {}"
   148 
   149 definition size :: "('a, 'b) mapping \<Rightarrow> nat"
   150 where
   151   "size m = (if finite (keys m) then card (keys m) else 0)"
   152 
   153 definition replace :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   154 where
   155   "replace k v m = (if k \<in> keys m then update k v m else m)"
   156 
   157 definition default :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   158 where
   159   "default k v m = (if k \<in> keys m then m else update k v m)"
   160 
   161 text \<open>Manual derivation of transfer rule is non-trivial\<close>
   162 
   163 lift_definition map_entry :: "'a \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" is
   164   "\<lambda>k f m. (case m k of None \<Rightarrow> m
   165     | Some v \<Rightarrow> m (k \<mapsto> (f v)))" parametric map_entry_parametric .
   166 
   167 lemma map_entry_code [code]:
   168   "map_entry k f m = (case lookup m k of None \<Rightarrow> m
   169     | Some v \<Rightarrow> update k (f v) m)"
   170   by transfer rule
   171 
   172 definition map_default :: "'a \<Rightarrow> 'b \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   173 where
   174   "map_default k v f m = map_entry k f (default k v m)" 
   175 
   176 definition of_alist :: "('k \<times> 'v) list \<Rightarrow> ('k, 'v) mapping"
   177 where
   178   "of_alist xs = foldr (\<lambda>(k, v) m. update k v m) xs empty"
   179 
   180 instantiation mapping :: (type, type) equal
   181 begin
   182 
   183 definition
   184   "HOL.equal m1 m2 \<longleftrightarrow> (\<forall>k. lookup m1 k = lookup m2 k)"
   185 
   186 instance
   187   by standard (unfold equal_mapping_def, transfer, auto)
   188 
   189 end
   190 
   191 context
   192 begin
   193 
   194 interpretation lifting_syntax .
   195 
   196 lemma [transfer_rule]:
   197   assumes [transfer_rule]: "bi_total A"
   198   assumes [transfer_rule]: "bi_unique B"
   199   shows "(pcr_mapping A B ===> pcr_mapping A B ===> op=) HOL.eq HOL.equal"
   200   by (unfold equal) transfer_prover
   201 
   202 lemma of_alist_transfer [transfer_rule]:
   203   assumes [transfer_rule]: "bi_unique R1"
   204   shows "(list_all2 (rel_prod R1 R2) ===> pcr_mapping R1 R2) map_of of_alist"
   205   unfolding of_alist_def [abs_def] map_of_foldr [abs_def] by transfer_prover
   206 
   207 end
   208 
   209 
   210 subsection \<open>Properties\<close>
   211 
   212 lemma lookup_update:
   213   "lookup (update k v m) k = Some v" 
   214   by transfer simp
   215 
   216 lemma lookup_update_neq:
   217   "k \<noteq> k' \<Longrightarrow> lookup (update k v m) k' = lookup m k'" 
   218   by transfer simp
   219 
   220 lemma lookup_empty:
   221   "lookup empty k = None" 
   222   by transfer simp
   223 
   224 lemma keys_is_none_rep [code_unfold]:
   225   "k \<in> keys m \<longleftrightarrow> \<not> (Option.is_none (lookup m k))"
   226   by transfer (auto simp add: Option.is_none_def)
   227 
   228 lemma update_update:
   229   "update k v (update k w m) = update k v m"
   230   "k \<noteq> l \<Longrightarrow> update k v (update l w m) = update l w (update k v m)"
   231   by (transfer, simp add: fun_upd_twist)+
   232 
   233 lemma update_delete [simp]:
   234   "update k v (delete k m) = update k v m"
   235   by transfer simp
   236 
   237 lemma delete_update:
   238   "delete k (update k v m) = delete k m"
   239   "k \<noteq> l \<Longrightarrow> delete k (update l v m) = update l v (delete k m)"
   240   by (transfer, simp add: fun_upd_twist)+
   241 
   242 lemma delete_empty [simp]:
   243   "delete k empty = empty"
   244   by transfer simp
   245 
   246 lemma replace_update:
   247   "k \<notin> keys m \<Longrightarrow> replace k v m = m"
   248   "k \<in> keys m \<Longrightarrow> replace k v m = update k v m"
   249   by (transfer, auto simp add: replace_def fun_upd_twist)+
   250 
   251 lemma size_empty [simp]:
   252   "size empty = 0"
   253   unfolding size_def by transfer simp
   254 
   255 lemma size_update:
   256   "finite (keys m) \<Longrightarrow> size (update k v m) =
   257     (if k \<in> keys m then size m else Suc (size m))"
   258   unfolding size_def by transfer (auto simp add: insert_dom)
   259 
   260 lemma size_delete:
   261   "size (delete k m) = (if k \<in> keys m then size m - 1 else size m)"
   262   unfolding size_def by transfer simp
   263 
   264 lemma size_tabulate [simp]:
   265   "size (tabulate ks f) = length (remdups ks)"
   266   unfolding size_def by transfer (auto simp add: map_of_map_restrict  card_set comp_def)
   267 
   268 lemma bulkload_tabulate:
   269   "bulkload xs = tabulate [0..<length xs] (nth xs)"
   270   by transfer (auto simp add: map_of_map_restrict)
   271 
   272 lemma is_empty_empty [simp]:
   273   "is_empty empty"
   274   unfolding is_empty_def by transfer simp 
   275 
   276 lemma is_empty_update [simp]:
   277   "\<not> is_empty (update k v m)"
   278   unfolding is_empty_def by transfer simp
   279 
   280 lemma is_empty_delete:
   281   "is_empty (delete k m) \<longleftrightarrow> is_empty m \<or> keys m = {k}"
   282   unfolding is_empty_def by transfer (auto simp del: dom_eq_empty_conv)
   283 
   284 lemma is_empty_replace [simp]:
   285   "is_empty (replace k v m) \<longleftrightarrow> is_empty m"
   286   unfolding is_empty_def replace_def by transfer auto
   287 
   288 lemma is_empty_default [simp]:
   289   "\<not> is_empty (default k v m)"
   290   unfolding is_empty_def default_def by transfer auto
   291 
   292 lemma is_empty_map_entry [simp]:
   293   "is_empty (map_entry k f m) \<longleftrightarrow> is_empty m"
   294   unfolding is_empty_def by transfer (auto split: option.split)
   295 
   296 lemma is_empty_map_default [simp]:
   297   "\<not> is_empty (map_default k v f m)"
   298   by (simp add: map_default_def)
   299 
   300 lemma keys_dom_lookup:
   301   "keys m = dom (Mapping.lookup m)"
   302   by transfer rule
   303 
   304 lemma keys_empty [simp]:
   305   "keys empty = {}"
   306   by transfer simp
   307 
   308 lemma keys_update [simp]:
   309   "keys (update k v m) = insert k (keys m)"
   310   by transfer simp
   311 
   312 lemma keys_delete [simp]:
   313   "keys (delete k m) = keys m - {k}"
   314   by transfer simp
   315 
   316 lemma keys_replace [simp]:
   317   "keys (replace k v m) = keys m"
   318   unfolding replace_def by transfer (simp add: insert_absorb)
   319 
   320 lemma keys_default [simp]:
   321   "keys (default k v m) = insert k (keys m)"
   322   unfolding default_def by transfer (simp add: insert_absorb)
   323 
   324 lemma keys_map_entry [simp]:
   325   "keys (map_entry k f m) = keys m"
   326   by transfer (auto split: option.split)
   327 
   328 lemma keys_map_default [simp]:
   329   "keys (map_default k v f m) = insert k (keys m)"
   330   by (simp add: map_default_def)
   331 
   332 lemma keys_tabulate [simp]:
   333   "keys (tabulate ks f) = set ks"
   334   by transfer (simp add: map_of_map_restrict o_def)
   335 
   336 lemma keys_bulkload [simp]:
   337   "keys (bulkload xs) = {0..<length xs}"
   338   by (simp add: bulkload_tabulate)
   339 
   340 lemma distinct_ordered_keys [simp]:
   341   "distinct (ordered_keys m)"
   342   by (simp add: ordered_keys_def)
   343 
   344 lemma ordered_keys_infinite [simp]:
   345   "\<not> finite (keys m) \<Longrightarrow> ordered_keys m = []"
   346   by (simp add: ordered_keys_def)
   347 
   348 lemma ordered_keys_empty [simp]:
   349   "ordered_keys empty = []"
   350   by (simp add: ordered_keys_def)
   351 
   352 lemma ordered_keys_update [simp]:
   353   "k \<in> keys m \<Longrightarrow> ordered_keys (update k v m) = ordered_keys m"
   354   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (update k v m) = insort k (ordered_keys m)"
   355   by (simp_all add: ordered_keys_def) (auto simp only: sorted_list_of_set_insert [symmetric] insert_absorb)
   356 
   357 lemma ordered_keys_delete [simp]:
   358   "ordered_keys (delete k m) = remove1 k (ordered_keys m)"
   359 proof (cases "finite (keys m)")
   360   case False then show ?thesis by simp
   361 next
   362   case True note fin = True
   363   show ?thesis
   364   proof (cases "k \<in> keys m")
   365     case False with fin have "k \<notin> set (sorted_list_of_set (keys m))" by simp
   366     with False show ?thesis by (simp add: ordered_keys_def remove1_idem)
   367   next
   368     case True with fin show ?thesis by (simp add: ordered_keys_def sorted_list_of_set_remove)
   369   qed
   370 qed
   371 
   372 lemma ordered_keys_replace [simp]:
   373   "ordered_keys (replace k v m) = ordered_keys m"
   374   by (simp add: replace_def)
   375 
   376 lemma ordered_keys_default [simp]:
   377   "k \<in> keys m \<Longrightarrow> ordered_keys (default k v m) = ordered_keys m"
   378   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (default k v m) = insort k (ordered_keys m)"
   379   by (simp_all add: default_def)
   380 
   381 lemma ordered_keys_map_entry [simp]:
   382   "ordered_keys (map_entry k f m) = ordered_keys m"
   383   by (simp add: ordered_keys_def)
   384 
   385 lemma ordered_keys_map_default [simp]:
   386   "k \<in> keys m \<Longrightarrow> ordered_keys (map_default k v f m) = ordered_keys m"
   387   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (map_default k v f m) = insort k (ordered_keys m)"
   388   by (simp_all add: map_default_def)
   389 
   390 lemma ordered_keys_tabulate [simp]:
   391   "ordered_keys (tabulate ks f) = sort (remdups ks)"
   392   by (simp add: ordered_keys_def sorted_list_of_set_sort_remdups)
   393 
   394 lemma ordered_keys_bulkload [simp]:
   395   "ordered_keys (bulkload ks) = [0..<length ks]"
   396   by (simp add: ordered_keys_def)
   397 
   398 lemma tabulate_fold:
   399   "tabulate xs f = fold (\<lambda>k m. update k (f k) m) xs empty"
   400 proof transfer
   401   fix f :: "'a \<Rightarrow> 'b" and xs
   402   have "map_of (List.map (\<lambda>k. (k, f k)) xs) = foldr (\<lambda>k m. m(k \<mapsto> f k)) xs Map.empty"
   403     by (simp add: foldr_map comp_def map_of_foldr)
   404   also have "foldr (\<lambda>k m. m(k \<mapsto> f k)) xs = fold (\<lambda>k m. m(k \<mapsto> f k)) xs"
   405     by (rule foldr_fold) (simp add: fun_eq_iff)
   406   ultimately show "map_of (List.map (\<lambda>k. (k, f k)) xs) = fold (\<lambda>k m. m(k \<mapsto> f k)) xs Map.empty"
   407     by simp
   408 qed
   409 
   410 
   411 subsection \<open>Code generator setup\<close>
   412 
   413 hide_const (open) empty is_empty rep lookup update delete ordered_keys keys size
   414   replace default map_entry map_default tabulate bulkload map of_alist
   415 
   416 end
   417