# HG changeset patch # User haftmann # Date 1397045298 -7200 # Node ID f732e6f3bf7fbf8577bb87c6d2685644c70a1d85 # Parent 907f04603177ebf4c493b2ffcafe137f714ba807 removed duplication and tuned diff -r 907f04603177 -r f732e6f3bf7f src/HOL/Library/Mapping.thy --- a/src/HOL/Library/Mapping.thy Thu Apr 10 17:48:54 2014 +0200 +++ b/src/HOL/Library/Mapping.thy Wed Apr 09 14:08:18 2014 +0200 @@ -12,61 +12,70 @@ context begin + interpretation lifting_syntax . -lemma empty_transfer: "(A ===> rel_option B) Map.empty Map.empty" by transfer_prover +lemma empty_transfer: + "(A ===> rel_option B) Map.empty Map.empty" + by transfer_prover -lemma lookup_transfer: "((A ===> B) ===> A ===> B) (\m k. m k) (\m k. m k)" by transfer_prover +lemma lookup_transfer: "((A ===> B) ===> A ===> B) (\m k. m k) (\m k. m k)" + by transfer_prover lemma update_transfer: assumes [transfer_rule]: "bi_unique A" - shows "(A ===> B ===> (A ===> rel_option B) ===> A ===> rel_option B) - (\k v m. m(k \ v)) (\k v m. m(k \ v))" -by transfer_prover + shows "(A ===> B ===> (A ===> rel_option B) ===> A ===> rel_option B) + (\k v m. m(k \ v)) (\k v m. m(k \ v))" + by transfer_prover lemma delete_transfer: assumes [transfer_rule]: "bi_unique A" shows "(A ===> (A ===> rel_option B) ===> A ===> rel_option B) - (\k m. m(k := None)) (\k m. m(k := None))" -by transfer_prover + (\k m. m(k := None)) (\k m. m(k := None))" + by transfer_prover -definition equal_None :: "'a option \ bool" where "equal_None x \ x = None" - -lemma [transfer_rule]: "(rel_option A ===> op=) equal_None equal_None" -unfolding rel_fun_def rel_option_iff equal_None_def by (auto split: option.split) +lemma is_none_parametric [transfer_rule]: + "(rel_option A ===> HOL.eq) Option.is_none Option.is_none" + by (auto simp add: is_none_def rel_fun_def rel_option_iff split: option.split) lemma dom_transfer: assumes [transfer_rule]: "bi_total A" shows "((A ===> rel_option B) ===> rel_set A) dom dom" -unfolding dom_def[abs_def] equal_None_def[symmetric] -by transfer_prover + unfolding dom_def [abs_def] is_none_def [symmetric] by transfer_prover lemma map_of_transfer [transfer_rule]: assumes [transfer_rule]: "bi_unique R1" shows "(list_all2 (rel_prod R1 R2) ===> R1 ===> rel_option R2) map_of map_of" -unfolding map_of_def by transfer_prover + unfolding map_of_def by transfer_prover lemma tabulate_transfer: assumes [transfer_rule]: "bi_unique A" shows "(list_all2 A ===> (A ===> B) ===> A ===> rel_option B) - (\ks f. (map_of (List.map (\k. (k, f k)) ks))) (\ks f. (map_of (List.map (\k. (k, f k)) ks)))" -by transfer_prover + (\ks f. (map_of (map (\k. (k, f k)) ks))) (\ks f. (map_of (map (\k. (k, f k)) ks)))" + by transfer_prover lemma bulkload_transfer: - "(list_all2 A ===> op= ===> rel_option A) + "(list_all2 A ===> HOL.eq ===> rel_option A) (\xs k. if k < length xs then Some (xs ! k) else None) (\xs k. if k < length xs then Some (xs ! k) else None)" -unfolding rel_fun_def -apply clarsimp -apply (erule list_all2_induct) - apply simp -apply (case_tac xa) - apply simp -by (auto dest: list_all2_lengthD list_all2_nthD) +proof + fix xs ys + assume "list_all2 A xs ys" + then show "(HOL.eq ===> rel_option A) + (\k. if k < length xs then Some (xs ! k) else None) + (\k. if k < length ys then Some (ys ! k) else None)" + apply induct + apply auto + unfolding rel_fun_def + apply clarsimp + apply (case_tac xa) + apply (auto dest: list_all2_lengthD list_all2_nthD) + done +qed lemma map_transfer: "((A ===> B) ===> (C ===> D) ===> (B ===> rel_option C) ===> A ===> rel_option D) - (\f g m. (map_option g \ m \ f)) (\f g m. (map_option g \ m \ f))" -by transfer_prover + (\f g m. (map_option g \ m \ f)) (\f g m. (map_option g \ m \ f))" + by transfer_prover lemma map_entry_transfer: assumes [transfer_rule]: "bi_unique A" @@ -74,38 +83,41 @@ (\k f m. (case m k of None \ m | Some v \ m (k \ (f v)))) (\k f m. (case m k of None \ m | Some v \ m (k \ (f v))))" -by transfer_prover + by transfer_prover end subsection {* Type definition and primitive operations *} typedef ('a, 'b) mapping = "UNIV :: ('a \ 'b) set" - morphisms rep Mapping .. + morphisms rep Mapping + .. -setup_lifting(no_code) type_definition_mapping - -lift_definition empty :: "('a, 'b) mapping" is Map.empty parametric empty_transfer . +setup_lifting (no_code) type_definition_mapping -lift_definition lookup :: "('a, 'b) mapping \ 'a \ 'b option" is "\m k. m k" - parametric lookup_transfer . +lift_definition empty :: "('a, 'b) mapping" + is Map.empty parametric empty_transfer . -lift_definition update :: "'a \ 'b \ ('a, 'b) mapping \ ('a, 'b) mapping" is "\k v m. m(k \ v)" - parametric update_transfer . +lift_definition lookup :: "('a, 'b) mapping \ 'a \ 'b option" + is "\m k. m k" parametric lookup_transfer . + +lift_definition update :: "'a \ 'b \ ('a, 'b) mapping \ ('a, 'b) mapping" + is "\k v m. m(k \ v)" parametric update_transfer . -lift_definition delete :: "'a \ ('a, 'b) mapping \ ('a, 'b) mapping" is "\k m. m(k := None)" - parametric delete_transfer . +lift_definition delete :: "'a \ ('a, 'b) mapping \ ('a, 'b) mapping" + is "\k m. m(k := None)" parametric delete_transfer . -lift_definition keys :: "('a, 'b) mapping \ 'a set" is dom parametric dom_transfer . +lift_definition keys :: "('a, 'b) mapping \ 'a set" + is dom parametric dom_transfer . -lift_definition tabulate :: "'a list \ ('a \ 'b) \ ('a, 'b) mapping" is - "\ks f. (map_of (List.map (\k. (k, f k)) ks))" parametric tabulate_transfer . +lift_definition tabulate :: "'a list \ ('a \ 'b) \ ('a, 'b) mapping" + is "\ks f. (map_of (List.map (\k. (k, f k)) ks))" parametric tabulate_transfer . -lift_definition bulkload :: "'a list \ (nat, 'a) mapping" is - "\xs k. if k < length xs then Some (xs ! k) else None" parametric bulkload_transfer . +lift_definition bulkload :: "'a list \ (nat, 'a) mapping" + is "\xs k. if k < length xs then Some (xs ! k) else None" parametric bulkload_transfer . -lift_definition map :: "('c \ 'a) \ ('b \ 'd) \ ('a, 'b) mapping \ ('c, 'd) mapping" is - "\f g m. (map_option g \ m \ f)" parametric map_transfer . +lift_definition map :: "('c \ 'a) \ ('b \ 'd) \ ('a, 'b) mapping \ ('c, 'd) mapping" + is "\f g m. (map_option g \ m \ f)" parametric map_transfer . subsection {* Functorial structure *} @@ -116,19 +128,24 @@ subsection {* Derived operations *} -definition ordered_keys :: "('a\linorder, 'b) mapping \ 'a list" where +definition ordered_keys :: "('a\linorder, 'b) mapping \ 'a list" +where "ordered_keys m = (if finite (keys m) then sorted_list_of_set (keys m) else [])" -definition is_empty :: "('a, 'b) mapping \ bool" where +definition is_empty :: "('a, 'b) mapping \ bool" +where "is_empty m \ keys m = {}" -definition size :: "('a, 'b) mapping \ nat" where +definition size :: "('a, 'b) mapping \ nat" +where "size m = (if finite (keys m) then card (keys m) else 0)" -definition replace :: "'a \ 'b \ ('a, 'b) mapping \ ('a, 'b) mapping" where +definition replace :: "'a \ 'b \ ('a, 'b) mapping \ ('a, 'b) mapping" +where "replace k v m = (if k \ keys m then update k v m else m)" -definition default :: "'a \ 'b \ ('a, 'b) mapping \ ('a, 'b) mapping" where +definition default :: "'a \ 'b \ ('a, 'b) mapping \ ('a, 'b) mapping" +where "default k v m = (if k \ keys m then m else update k v m)" lift_definition map_entry :: "'a \ ('b \ 'b) \ ('a, 'b) mapping \ ('a, 'b) mapping" is @@ -139,15 +156,16 @@ | Some v \ update k (f v) m)" by transfer rule -definition map_default :: "'a \ 'b \ ('b \ 'b) \ ('a, 'b) mapping \ ('a, 'b) mapping" where +definition map_default :: "'a \ 'b \ ('b \ 'b) \ ('a, 'b) mapping \ ('a, 'b) mapping" +where "map_default k v f m = map_entry k f (default k v m)" lift_definition of_alist :: "('k \ 'v) list \ ('k, 'v) mapping" -is map_of parametric map_of_transfer . + is map_of parametric map_of_transfer . lemma of_alist_code [code]: "of_alist xs = foldr (\(k, v) m. update k v m) xs empty" -by transfer(simp add: map_add_map_of_foldr[symmetric]) + by transfer (simp add: map_add_map_of_foldr [symmetric]) instantiation mapping :: (type, type) equal begin @@ -162,35 +180,36 @@ context begin + interpretation lifting_syntax . lemma [transfer_rule]: assumes [transfer_rule]: "bi_total A" assumes [transfer_rule]: "bi_unique B" - shows "(pcr_mapping A B ===> pcr_mapping A B ===> op=) HOL.eq HOL.equal" -by (unfold equal) transfer_prover + shows "(pcr_mapping A B ===> pcr_mapping A B ===> op=) HOL.eq HOL.equal" + by (unfold equal) transfer_prover end + subsection {* Properties *} -lemma lookup_update: "lookup (update k v m) k = Some v" +lemma lookup_update: + "lookup (update k v m) k = Some v" by transfer simp -lemma lookup_update_neq: "k \ k' \ lookup (update k v m) k' = lookup m k'" +lemma lookup_update_neq: + "k \ k' \ lookup (update k v m) k' = lookup m k'" by transfer simp -lemma lookup_empty: "lookup empty k = None" +lemma lookup_empty: + "lookup empty k = None" by transfer simp lemma keys_is_none_rep [code_unfold]: "k \ keys m \ \ (Option.is_none (lookup m k))" by transfer (auto simp add: is_none_def) -lemma tabulate_alt_def: - "map_of (List.map (\k. (k, f k)) ks) = (Some o f) |` set ks" - by (induct ks) (auto simp add: tabulate_def restrict_map_def) - lemma update_update: "update k v (update k w m) = update k v m" "k \ l \ update k v (update l w m) = update l w (update k v m)" @@ -229,11 +248,11 @@ lemma size_tabulate [simp]: "size (tabulate ks f) = length (remdups ks)" - unfolding size_def by transfer (auto simp add: tabulate_alt_def card_set comp_def) + unfolding size_def by transfer (auto simp add: map_of_map_restrict card_set comp_def) lemma bulkload_tabulate: "bulkload xs = tabulate [0.. is_empty m" - unfolding is_empty_def - apply transfer by (case_tac "m k") auto + unfolding is_empty_def by transfer (auto split: option.split) lemma is_empty_map_default [simp]: "\ is_empty (map_default k v f m)" @@ -286,7 +304,7 @@ lemma keys_map_entry [simp]: "keys (map_entry k f m) = keys m" - apply transfer by (case_tac "m k") auto + by transfer (auto split: option.split) lemma keys_map_default [simp]: "keys (map_default k v f m) = insert k (keys m)" @@ -298,7 +316,7 @@ lemma keys_bulkload [simp]: "keys (bulkload xs) = {0..k m. update k (f k) m) xs empty" +proof transfer + fix f :: "'a \ 'b" and xs + from map_add_map_of_foldr + have "Map.empty ++ map_of (List.map (\k. (k, f k)) xs) = + foldr (\(k, v) m. m(k \ v)) (List.map (\k. (k, f k)) xs) Map.empty" + . + then have "map_of (List.map (\k. (k, f k)) xs) = foldr (\k m. m(k \ f k)) xs Map.empty" + by (simp add: foldr_map comp_def) + also have "foldr (\k m. m(k \ f k)) xs = fold (\k m. m(k \ f k)) xs" + by (rule foldr_fold) (simp add: fun_eq_iff) + ultimately show "map_of (List.map (\k. (k, f k)) xs) = fold (\k m. m(k \ f k)) xs Map.empty" + by simp +qed + subsection {* Code generator setup *}