src/HOL/Library/Mapping.thy
changeset 56529 aff193f53a64
parent 56528 f732e6f3bf7f
child 56545 8f1e7596deb7
equal deleted inserted replaced
56528:f732e6f3bf7f 56529:aff193f53a64
     8 imports Main
     8 imports Main
     9 begin
     9 begin
    10 
    10 
    11 subsection {* Parametricity transfer rules *}
    11 subsection {* Parametricity transfer rules *}
    12 
    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 
    13 context
    17 context
    14 begin
    18 begin
    15 
    19 
    16 interpretation lifting_syntax .
    20 interpretation lifting_syntax .
    17 
    21 
    18 lemma empty_transfer:
    22 lemma empty_parametric:
    19   "(A ===> rel_option B) Map.empty Map.empty"
    23   "(A ===> rel_option B) Map.empty Map.empty"
    20   by transfer_prover
    24   by transfer_prover
    21 
    25 
    22 lemma lookup_transfer: "((A ===> B) ===> A ===> B) (\<lambda>m k. m k) (\<lambda>m k. m k)"
    26 lemma lookup_parametric: "((A ===> B) ===> A ===> B) (\<lambda>m k. m k) (\<lambda>m k. m k)"
    23   by transfer_prover
    27   by transfer_prover
    24 
    28 
    25 lemma update_transfer:
    29 lemma update_parametric:
    26   assumes [transfer_rule]: "bi_unique A"
    30   assumes [transfer_rule]: "bi_unique A"
    27   shows "(A ===> B ===> (A ===> rel_option B) ===> A ===> rel_option B)
    31   shows "(A ===> B ===> (A ===> rel_option B) ===> A ===> rel_option B)
    28     (\<lambda>k v m. m(k \<mapsto> v)) (\<lambda>k v m. m(k \<mapsto> v))"
    32     (\<lambda>k v m. m(k \<mapsto> v)) (\<lambda>k v m. m(k \<mapsto> v))"
    29   by transfer_prover
    33   by transfer_prover
    30 
    34 
    31 lemma delete_transfer:
    35 lemma delete_parametric:
    32   assumes [transfer_rule]: "bi_unique A"
    36   assumes [transfer_rule]: "bi_unique A"
    33   shows "(A ===> (A ===> rel_option B) ===> A ===> rel_option B) 
    37   shows "(A ===> (A ===> rel_option B) ===> A ===> rel_option B) 
    34     (\<lambda>k m. m(k := None)) (\<lambda>k m. m(k := None))"
    38     (\<lambda>k m. m(k := None)) (\<lambda>k m. m(k := None))"
    35   by transfer_prover
    39   by transfer_prover
    36 
    40 
    37 lemma is_none_parametric [transfer_rule]:
    41 lemma is_none_parametric [transfer_rule]:
    38   "(rel_option A ===> HOL.eq) Option.is_none Option.is_none"
    42   "(rel_option A ===> HOL.eq) Option.is_none Option.is_none"
    39   by (auto simp add: is_none_def rel_fun_def rel_option_iff split: option.split)
    43   by (auto simp add: is_none_def rel_fun_def rel_option_iff split: option.split)
    40 
    44 
    41 lemma dom_transfer:
    45 lemma dom_parametric:
    42   assumes [transfer_rule]: "bi_total A"
    46   assumes [transfer_rule]: "bi_total A"
    43   shows "((A ===> rel_option B) ===> rel_set A) dom dom" 
    47   shows "((A ===> rel_option B) ===> rel_set A) dom dom" 
    44   unfolding dom_def [abs_def] is_none_def [symmetric] by transfer_prover
    48   unfolding dom_def [abs_def] is_none_def [symmetric] by transfer_prover
    45 
    49 
    46 lemma map_of_transfer [transfer_rule]:
    50 lemma map_of_parametric [transfer_rule]:
    47   assumes [transfer_rule]: "bi_unique R1"
    51   assumes [transfer_rule]: "bi_unique R1"
    48   shows "(list_all2 (rel_prod R1 R2) ===> R1 ===> rel_option R2) map_of map_of"
    52   shows "(list_all2 (rel_prod R1 R2) ===> R1 ===> rel_option R2) map_of map_of"
    49   unfolding map_of_def by transfer_prover
    53   unfolding map_of_def by transfer_prover
    50 
    54 
    51 lemma tabulate_transfer: 
    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: 
    52   assumes [transfer_rule]: "bi_unique A"
    64   assumes [transfer_rule]: "bi_unique A"
    53   shows "(list_all2 A ===> (A ===> B) ===> A ===> rel_option B) 
    65   shows "(list_all2 A ===> (A ===> B) ===> A ===> rel_option B) 
    54     (\<lambda>ks f. (map_of (map (\<lambda>k. (k, f k)) ks))) (\<lambda>ks f. (map_of (map (\<lambda>k. (k, f k)) ks)))"
    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)))"
    55   by transfer_prover
    67   by transfer_prover
    56 
    68 
    57 lemma bulkload_transfer: 
    69 lemma bulkload_parametric: 
    58   "(list_all2 A ===> HOL.eq ===> rel_option A) 
    70   "(list_all2 A ===> HOL.eq ===> rel_option A) 
    59     (\<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)"
    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)"
    60 proof
    72 proof
    61   fix xs ys
    73   fix xs ys
    62   assume "list_all2 A xs ys"
    74   assume "list_all2 A xs ys"
    70     apply (case_tac xa) 
    82     apply (case_tac xa) 
    71     apply (auto dest: list_all2_lengthD list_all2_nthD)
    83     apply (auto dest: list_all2_lengthD list_all2_nthD)
    72     done
    84     done
    73 qed
    85 qed
    74 
    86 
    75 lemma map_transfer: 
    87 lemma map_parametric: 
    76   "((A ===> B) ===> (C ===> D) ===> (B ===> rel_option C) ===> A ===> rel_option D) 
    88   "((A ===> B) ===> (C ===> D) ===> (B ===> rel_option C) ===> A ===> rel_option D) 
    77      (\<lambda>f g m. (map_option g \<circ> m \<circ> f)) (\<lambda>f g m. (map_option g \<circ> m \<circ> f))"
    89      (\<lambda>f g m. (map_option g \<circ> m \<circ> f)) (\<lambda>f g m. (map_option g \<circ> m \<circ> f))"
    78   by transfer_prover
    90   by transfer_prover
    79 
    91 
    80 lemma map_entry_transfer:
       
    81   assumes [transfer_rule]: "bi_unique A"
       
    82   shows "(A ===> (B ===> B) ===> (A ===> rel_option B) ===> A ===> rel_option B) 
       
    83     (\<lambda>k f m. (case m k of None \<Rightarrow> m
       
    84       | Some v \<Rightarrow> m (k \<mapsto> (f v)))) (\<lambda>k f m. (case m k of None \<Rightarrow> m
       
    85       | Some v \<Rightarrow> m (k \<mapsto> (f v))))"
       
    86   by transfer_prover
       
    87 
       
    88 end
    92 end
       
    93 
    89 
    94 
    90 subsection {* Type definition and primitive operations *}
    95 subsection {* Type definition and primitive operations *}
    91 
    96 
    92 typedef ('a, 'b) mapping = "UNIV :: ('a \<rightharpoonup> 'b) set"
    97 typedef ('a, 'b) mapping = "UNIV :: ('a \<rightharpoonup> 'b) set"
    93   morphisms rep Mapping
    98   morphisms rep Mapping
    94   ..
    99   ..
    95 
   100 
    96 setup_lifting (no_code) type_definition_mapping
   101 setup_lifting (no_code) type_definition_mapping
    97 
   102 
    98 lift_definition empty :: "('a, 'b) mapping"
   103 lift_definition empty :: "('a, 'b) mapping"
    99   is Map.empty parametric empty_transfer .
   104   is Map.empty parametric empty_parametric .
   100 
   105 
   101 lift_definition lookup :: "('a, 'b) mapping \<Rightarrow> 'a \<Rightarrow> 'b option"
   106 lift_definition lookup :: "('a, 'b) mapping \<Rightarrow> 'a \<Rightarrow> 'b option"
   102   is "\<lambda>m k. m k" parametric lookup_transfer .
   107   is "\<lambda>m k. m k" parametric lookup_parametric .
   103 
   108 
   104 lift_definition update :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   109 lift_definition update :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   105   is "\<lambda>k v m. m(k \<mapsto> v)" parametric update_transfer .
   110   is "\<lambda>k v m. m(k \<mapsto> v)" parametric update_parametric .
   106 
   111 
   107 lift_definition delete :: "'a \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   112 lift_definition delete :: "'a \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   108   is "\<lambda>k m. m(k := None)" parametric delete_transfer .
   113   is "\<lambda>k m. m(k := None)" parametric delete_parametric .
   109 
   114 
   110 lift_definition keys :: "('a, 'b) mapping \<Rightarrow> 'a set"
   115 lift_definition keys :: "('a, 'b) mapping \<Rightarrow> 'a set"
   111   is dom parametric dom_transfer .
   116   is dom parametric dom_parametric .
   112 
   117 
   113 lift_definition tabulate :: "'a list \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping"
   118 lift_definition tabulate :: "'a list \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping"
   114   is "\<lambda>ks f. (map_of (List.map (\<lambda>k. (k, f k)) ks))" parametric tabulate_transfer .
   119   is "\<lambda>ks f. (map_of (List.map (\<lambda>k. (k, f k)) ks))" parametric tabulate_parametric .
   115 
   120 
   116 lift_definition bulkload :: "'a list \<Rightarrow> (nat, 'a) mapping"
   121 lift_definition bulkload :: "'a list \<Rightarrow> (nat, 'a) mapping"
   117   is "\<lambda>xs k. if k < length xs then Some (xs ! k) else None" parametric bulkload_transfer .
   122   is "\<lambda>xs k. if k < length xs then Some (xs ! k) else None" parametric bulkload_parametric .
   118 
   123 
   119 lift_definition map :: "('c \<Rightarrow> 'a) \<Rightarrow> ('b \<Rightarrow> 'd) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('c, 'd) mapping"
   124 lift_definition map :: "('c \<Rightarrow> 'a) \<Rightarrow> ('b \<Rightarrow> 'd) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('c, 'd) mapping"
   120   is "\<lambda>f g m. (map_option g \<circ> m \<circ> f)" parametric map_transfer .
   125   is "\<lambda>f g m. (map_option g \<circ> m \<circ> f)" parametric map_parametric .
   121 
   126 
   122 
   127 
   123 subsection {* Functorial structure *}
   128 subsection {* Functorial structure *}
   124 
   129 
   125 functor map: map
   130 functor map: map
   146 
   151 
   147 definition default :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   152 definition default :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   148 where
   153 where
   149   "default k v m = (if k \<in> keys m then m else update k v m)"
   154   "default k v m = (if k \<in> keys m then m else update k v m)"
   150 
   155 
       
   156 text {* Manual derivation of transfer rule is non-trivial *}
       
   157 
   151 lift_definition map_entry :: "'a \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" is
   158 lift_definition map_entry :: "'a \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" is
   152   "\<lambda>k f m. (case m k of None \<Rightarrow> m
   159   "\<lambda>k f m. (case m k of None \<Rightarrow> m
   153     | Some v \<Rightarrow> m (k \<mapsto> (f v)))" parametric map_entry_transfer .
   160     | Some v \<Rightarrow> m (k \<mapsto> (f v)))" parametric map_entry_parametric .
   154 
   161 
   155 lemma map_entry_code [code]: "map_entry k f m = (case lookup m k of None \<Rightarrow> m
   162 lemma map_entry_code [code]:
       
   163   "map_entry k f m = (case lookup m k of None \<Rightarrow> m
   156     | Some v \<Rightarrow> update k (f v) m)"
   164     | Some v \<Rightarrow> update k (f v) m)"
   157   by transfer rule
   165   by transfer rule
   158 
   166 
   159 definition map_default :: "'a \<Rightarrow> 'b \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   167 definition map_default :: "'a \<Rightarrow> 'b \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping"
   160 where
   168 where
   161   "map_default k v f m = map_entry k f (default k v m)" 
   169   "map_default k v f m = map_entry k f (default k v m)" 
   162 
   170 
   163 lift_definition of_alist :: "('k \<times> 'v) list \<Rightarrow> ('k, 'v) mapping"
   171 definition of_alist :: "('k \<times> 'v) list \<Rightarrow> ('k, 'v) mapping"
   164   is map_of parametric map_of_transfer .
   172 where
   165 
       
   166 lemma of_alist_code [code]:
       
   167   "of_alist xs = foldr (\<lambda>(k, v) m. update k v m) xs empty"
   173   "of_alist xs = foldr (\<lambda>(k, v) m. update k v m) xs empty"
   168   by transfer (simp add: map_add_map_of_foldr [symmetric])
       
   169 
   174 
   170 instantiation mapping :: (type, type) equal
   175 instantiation mapping :: (type, type) equal
   171 begin
   176 begin
   172 
   177 
   173 definition
   178 definition
   186 lemma [transfer_rule]:
   191 lemma [transfer_rule]:
   187   assumes [transfer_rule]: "bi_total A"
   192   assumes [transfer_rule]: "bi_total A"
   188   assumes [transfer_rule]: "bi_unique B"
   193   assumes [transfer_rule]: "bi_unique B"
   189   shows "(pcr_mapping A B ===> pcr_mapping A B ===> op=) HOL.eq HOL.equal"
   194   shows "(pcr_mapping A B ===> pcr_mapping A B ===> op=) HOL.eq HOL.equal"
   190   by (unfold equal) transfer_prover
   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
   191 
   201 
   192 end
   202 end
   193 
   203 
   194 
   204 
   195 subsection {* Properties *}
   205 subsection {* Properties *}
   378 
   388 
   379 lemma tabulate_fold:
   389 lemma tabulate_fold:
   380   "tabulate xs f = fold (\<lambda>k m. update k (f k) m) xs empty"
   390   "tabulate xs f = fold (\<lambda>k m. update k (f k) m) xs empty"
   381 proof transfer
   391 proof transfer
   382   fix f :: "'a \<Rightarrow> 'b" and xs
   392   fix f :: "'a \<Rightarrow> 'b" and xs
   383   from map_add_map_of_foldr
   393   have "map_of (List.map (\<lambda>k. (k, f k)) xs) = foldr (\<lambda>k m. m(k \<mapsto> f k)) xs Map.empty"
   384   have "Map.empty ++ map_of (List.map (\<lambda>k. (k, f k)) xs) =
   394     by (simp add: foldr_map comp_def map_of_foldr)
   385     foldr (\<lambda>(k, v) m. m(k \<mapsto> v)) (List.map (\<lambda>k. (k, f k)) xs) Map.empty"
       
   386     .
       
   387   then have "map_of (List.map (\<lambda>k. (k, f k)) xs) = foldr (\<lambda>k m. m(k \<mapsto> f k)) xs Map.empty"
       
   388     by (simp add: foldr_map comp_def)
       
   389   also have "foldr (\<lambda>k m. m(k \<mapsto> f k)) xs = fold (\<lambda>k m. m(k \<mapsto> f k)) xs"
   395   also have "foldr (\<lambda>k m. m(k \<mapsto> f k)) xs = fold (\<lambda>k m. m(k \<mapsto> f k)) xs"
   390     by (rule foldr_fold) (simp add: fun_eq_iff)
   396     by (rule foldr_fold) (simp add: fun_eq_iff)
   391   ultimately show "map_of (List.map (\<lambda>k. (k, f k)) xs) = fold (\<lambda>k m. m(k \<mapsto> f k)) xs Map.empty"
   397   ultimately show "map_of (List.map (\<lambda>k. (k, f k)) xs) = fold (\<lambda>k m. m(k \<mapsto> f k)) xs Map.empty"
   392     by simp
   398     by simp
   393 qed
   399 qed