src/HOL/Library/AssocList.thy
changeset 23373 ead82c82da9e
parent 23281 e26ec695c9b3
child 25966 74f6817870f9
equal deleted inserted replaced
23372:0035be079bee 23373:ead82c82da9e
    17 *}
    17 *}
    18 
    18 
    19 fun
    19 fun
    20   delete :: "'key \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    20   delete :: "'key \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    21 where
    21 where
    22   "delete k [] = []"
    22     "delete k [] = []"
    23   | "delete k (p#ps) = (if fst p = k then delete k ps else p # delete k ps)"
    23   | "delete k (p#ps) = (if fst p = k then delete k ps else p # delete k ps)"
    24 
    24 
    25 fun
    25 fun
    26   update :: "'key \<Rightarrow> 'val \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    26   update :: "'key \<Rightarrow> 'val \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    27 where
    27 where
    77 termination by lexicographic_order
    77 termination by lexicographic_order
    78 
    78 
    79 fun
    79 fun
    80   restrict :: "'key set \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    80   restrict :: "'key set \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    81 where
    81 where
    82   "restrict A [] = []"
    82     "restrict A [] = []"
    83   | "restrict A (p#ps) = (if fst p \<in> A then p#restrict A ps else restrict A ps)"
    83   | "restrict A (p#ps) = (if fst p \<in> A then p#restrict A ps else restrict A ps)"
    84 
    84 
    85 fun
    85 fun
    86   map_ran :: "('key \<Rightarrow> 'val \<Rightarrow> 'val) \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    86   map_ran :: "('key \<Rightarrow> 'val \<Rightarrow> 'val) \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    87 where
    87 where
    88   "map_ran f [] = []"
    88     "map_ran f [] = []"
    89   | "map_ran f (p#ps) = (fst p, f (fst p) (snd p)) # map_ran f ps"
    89   | "map_ran f (p#ps) = (fst p, f (fst p) (snd p)) # map_ran f ps"
    90 
    90 
    91 fun
    91 fun
    92   clearjunk  :: "('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    92   clearjunk  :: "('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
    93 where
    93 where
    94   "clearjunk [] = []"  
    94     "clearjunk [] = []"  
    95   | "clearjunk (p#ps) = p # clearjunk (delete (fst p) ps)"
    95   | "clearjunk (p#ps) = p # clearjunk (delete (fst p) ps)"
    96 
    96 
    97 lemmas [simp del] = compose_hint
    97 lemmas [simp del] = compose_hint
    98 
    98 
    99 
    99 
   100 (* ******************************************************************************** *)
       
   101 subsection {* Lookup *}
   100 subsection {* Lookup *}
   102 (* ******************************************************************************** *)
       
   103 
   101 
   104 lemma lookup_simps [code func]: 
   102 lemma lookup_simps [code func]: 
   105   "map_of [] k = None"
   103   "map_of [] k = None"
   106   "map_of (p#ps) k = (if fst p = k then Some (snd p) else map_of ps k)"
   104   "map_of (p#ps) k = (if fst p = k then Some (snd p) else map_of ps k)"
   107   by simp_all
   105   by simp_all
   108 
   106 
   109 
   107 
   110 (* ******************************************************************************** *)
       
   111 subsection {* @{const delete} *}
   108 subsection {* @{const delete} *}
   112 (* ******************************************************************************** *)
       
   113 
   109 
   114 lemma delete_def:
   110 lemma delete_def:
   115   "delete k xs = filter (\<lambda>p. fst p \<noteq> k) xs"
   111   "delete k xs = filter (\<lambda>p. fst p \<noteq> k) xs"
   116   by (induct xs) auto
   112   by (induct xs) auto
   117 
   113 
   138   by (induct al) auto
   134   by (induct al) auto
   139 
   135 
   140 lemma distinct_delete:
   136 lemma distinct_delete:
   141   assumes "distinct (map fst al)" 
   137   assumes "distinct (map fst al)" 
   142   shows "distinct (map fst (delete k al))"
   138   shows "distinct (map fst (delete k al))"
   143 using prems
   139 using assms
   144 proof (induct al)
   140 proof (induct al)
   145   case Nil thus ?case by simp
   141   case Nil thus ?case by simp
   146 next
   142 next
   147   case (Cons a al)
   143   case (Cons a al)
   148   from Cons.prems obtain 
   144   from Cons.prems obtain 
   150     dist_al: "distinct (map fst al)"
   146     dist_al: "distinct (map fst al)"
   151     by auto
   147     by auto
   152   show ?case
   148   show ?case
   153   proof (cases "fst a = k")
   149   proof (cases "fst a = k")
   154     case True
   150     case True
   155     from True dist_al show ?thesis by simp
   151     with Cons dist_al show ?thesis by simp
   156   next
   152   next
   157     case False
   153     case False
   158     from dist_al
   154     from dist_al
   159     have "distinct (map fst (delete k al))"
   155     have "distinct (map fst (delete k al))"
   160       by (rule Cons.hyps)
   156       by (rule Cons.hyps)
   169   by (induct al) auto
   165   by (induct al) auto
   170 
   166 
   171 lemma clearjunk_delete: "clearjunk (delete x al) = delete x (clearjunk al)"
   167 lemma clearjunk_delete: "clearjunk (delete x al) = delete x (clearjunk al)"
   172   by (induct al rule: clearjunk.induct) (auto simp add: delete_idem delete_twist)
   168   by (induct al rule: clearjunk.induct) (auto simp add: delete_idem delete_twist)
   173 
   169 
   174 (* ******************************************************************************** *)
   170 
   175 subsection {* @{const clearjunk} *}
   171 subsection {* @{const clearjunk} *}
   176 (* ******************************************************************************** *)
       
   177 
   172 
   178 lemma insert_fst_filter: 
   173 lemma insert_fst_filter: 
   179   "insert a(fst ` {x \<in> set ps. fst x \<noteq> a}) = insert a (fst ` set ps)"
   174   "insert a(fst ` {x \<in> set ps. fst x \<noteq> a}) = insert a (fst ` set ps)"
   180   by (induct ps) auto
   175   by (induct ps) auto
   181 
   176 
   219   by (induct al rule: clearjunk.induct) (auto simp add: notin_fst_filter)
   214   by (induct al rule: clearjunk.induct) (auto simp add: notin_fst_filter)
   220 
   215 
   221 lemma clearjunk_idem: "clearjunk (clearjunk al) = clearjunk al"
   216 lemma clearjunk_idem: "clearjunk (clearjunk al) = clearjunk al"
   222   by simp
   217   by simp
   223 
   218 
   224 (* ******************************************************************************** *)
   219 
   225 subsection {* @{const dom} and @{term "ran"} *}
   220 subsection {* @{const dom} and @{term "ran"} *}
   226 (* ******************************************************************************** *)
       
   227 
   221 
   228 lemma dom_map_of': "fst ` set al = dom (map_of al)"
   222 lemma dom_map_of': "fst ` set al = dom (map_of al)"
   229   by (induct al) auto
   223   by (induct al) auto
   230 
   224 
   231 lemmas dom_map_of = dom_map_of' [symmetric]
   225 lemmas dom_map_of = dom_map_of' [symmetric]
   293   also have "\<dots> = snd ` set (clearjunk al)"
   287   also have "\<dots> = snd ` set (clearjunk al)"
   294     by (simp add: ran_distinct)
   288     by (simp add: ran_distinct)
   295   finally show ?thesis .
   289   finally show ?thesis .
   296 qed
   290 qed
   297    
   291    
   298 (* ******************************************************************************** *)
   292 
   299 subsection {* @{const update} *}
   293 subsection {* @{const update} *}
   300 (* ******************************************************************************** *)
       
   301 
   294 
   302 lemma update_conv: "map_of (update k v al) k' = ((map_of al)(k\<mapsto>v)) k'"
   295 lemma update_conv: "map_of (update k v al) k' = ((map_of al)(k\<mapsto>v)) k'"
   303   by (induct al) auto
   296   by (induct al) auto
   304 
   297 
   305 lemma update_conv': "map_of (update k v al)  = ((map_of al)(k\<mapsto>v))"
   298 lemma update_conv': "map_of (update k v al)  = ((map_of al)(k\<mapsto>v))"
   309   by (induct al) auto
   302   by (induct al) auto
   310 
   303 
   311 lemma distinct_update:
   304 lemma distinct_update:
   312   assumes "distinct (map fst al)" 
   305   assumes "distinct (map fst al)" 
   313   shows "distinct (map fst (update k v al))"
   306   shows "distinct (map fst (update k v al))"
   314 using prems
   307 using assms
   315 proof (induct al)
   308 proof (induct al)
   316   case Nil thus ?case by simp
   309   case Nil thus ?case by simp
   317 next
   310 next
   318   case (Cons a al)
   311   case (Cons a al)
   319   from Cons.prems obtain 
   312   from Cons.prems obtain 
   372 
   365 
   373 lemma image_update[simp]: "x \<notin> A \<Longrightarrow> map_of (update x y al) ` A = map_of al ` A"
   366 lemma image_update[simp]: "x \<notin> A \<Longrightarrow> map_of (update x y al) ` A = map_of al ` A"
   374   by (simp add: update_conv' image_map_upd)
   367   by (simp add: update_conv' image_map_upd)
   375 
   368 
   376 
   369 
   377 (* ******************************************************************************** *)
       
   378 subsection {* @{const updates} *}
   370 subsection {* @{const updates} *}
   379 (* ******************************************************************************** *)
       
   380 
   371 
   381 lemma updates_conv: "map_of (updates ks vs al) k = ((map_of al)(ks[\<mapsto>]vs)) k"
   372 lemma updates_conv: "map_of (updates ks vs al) k = ((map_of al)(ks[\<mapsto>]vs)) k"
   382 proof (induct ks arbitrary: vs al)
   373 proof (induct ks arbitrary: vs al)
   383   case Nil
   374   case Nil
   384   thus ?case by simp
   375   thus ?case by simp
   399   by (rule ext) (rule updates_conv)
   390   by (rule ext) (rule updates_conv)
   400 
   391 
   401 lemma distinct_updates:
   392 lemma distinct_updates:
   402   assumes "distinct (map fst al)"
   393   assumes "distinct (map fst al)"
   403   shows "distinct (map fst (updates ks vs al))"
   394   shows "distinct (map fst (updates ks vs al))"
   404   using prems
   395   using assms
   405   by (induct ks arbitrary: vs al)
   396   by (induct ks arbitrary: vs al)
   406    (auto simp add: distinct_update split: list.splits)
   397    (auto simp add: distinct_update split: list.splits)
   407 
   398 
   408 lemma clearjunk_updates:
   399 lemma clearjunk_updates:
   409  "clearjunk (updates ks vs al) = updates ks vs (clearjunk al)"
   400  "clearjunk (updates ks vs al) = updates ks vs (clearjunk al)"
   445 
   436 
   446 lemma updates_append2_drop[simp]:
   437 lemma updates_append2_drop[simp]:
   447   "size xs = size ys \<Longrightarrow> updates xs (ys@zs) al = updates xs ys al"
   438   "size xs = size ys \<Longrightarrow> updates xs (ys@zs) al = updates xs ys al"
   448   by (induct xs arbitrary: ys al) (auto split: list.splits)
   439   by (induct xs arbitrary: ys al) (auto split: list.splits)
   449 
   440 
   450 (* ******************************************************************************** *)
   441 
   451 subsection {* @{const map_ran} *}
   442 subsection {* @{const map_ran} *}
   452 (* ******************************************************************************** *)
       
   453 
   443 
   454 lemma map_ran_conv: "map_of (map_ran f al) k = option_map (f k) (map_of al k)"
   444 lemma map_ran_conv: "map_of (map_ran f al) k = option_map (f k) (map_of al k)"
   455   by (induct al) auto
   445   by (induct al) auto
   456 
   446 
   457 lemma dom_map_ran: "fst ` set (map_ran f al) = fst ` set al"
   447 lemma dom_map_ran: "fst ` set (map_ran f al) = fst ` set al"
   464   by (induct ps) auto
   454   by (induct ps) auto
   465 
   455 
   466 lemma clearjunk_map_ran: "clearjunk (map_ran f al) = map_ran f (clearjunk al)"
   456 lemma clearjunk_map_ran: "clearjunk (map_ran f al) = map_ran f (clearjunk al)"
   467   by (induct al rule: clearjunk.induct) (auto simp add: delete_def map_ran_filter)
   457   by (induct al rule: clearjunk.induct) (auto simp add: delete_def map_ran_filter)
   468 
   458 
   469 (* ******************************************************************************** *)
   459 
   470 subsection {* @{const merge} *}
   460 subsection {* @{const merge} *}
   471 (* ******************************************************************************** *)
       
   472 
   461 
   473 lemma dom_merge: "fst ` set (merge xs ys) = fst ` set xs \<union> fst ` set ys"
   462 lemma dom_merge: "fst ` set (merge xs ys) = fst ` set xs \<union> fst ` set ys"
   474   by (induct ys arbitrary: xs) (auto simp add: dom_update)
   463   by (induct ys arbitrary: xs) (auto simp add: dom_update)
   475 
   464 
   476 lemma distinct_merge:
   465 lemma distinct_merge:
   477   assumes "distinct (map fst xs)"
   466   assumes "distinct (map fst xs)"
   478   shows "distinct (map fst (merge xs ys))"
   467   shows "distinct (map fst (merge xs ys))"
   479   using prems
   468   using assms
   480 by (induct ys arbitrary: xs) (auto simp add: dom_merge distinct_update)
   469 by (induct ys arbitrary: xs) (auto simp add: dom_merge distinct_update)
   481 
   470 
   482 lemma clearjunk_merge:
   471 lemma clearjunk_merge:
   483  "clearjunk (merge xs ys) = merge (clearjunk xs) ys"
   472  "clearjunk (merge xs ys) = merge (clearjunk xs) ys"
   484   by (induct ys) (auto simp add: clearjunk_update)
   473   by (induct ys) (auto simp add: clearjunk_update)
   534   by (simp add: updates_conv' merge_conv')
   523   by (simp add: updates_conv' merge_conv')
   535 
   524 
   536 lemma merge_append: "map_of (xs@ys) = map_of (merge ys xs)"
   525 lemma merge_append: "map_of (xs@ys) = map_of (merge ys xs)"
   537   by (simp add: merge_conv')
   526   by (simp add: merge_conv')
   538 
   527 
   539 (* ******************************************************************************** *)
   528 
   540 subsection {* @{const compose} *}
   529 subsection {* @{const compose} *}
   541 (* ******************************************************************************** *)
       
   542 
   530 
   543 lemma compose_first_None [simp]: 
   531 lemma compose_first_None [simp]: 
   544   assumes "map_of xs k = None" 
   532   assumes "map_of xs k = None" 
   545   shows "map_of (compose xs ys) k = None"
   533   shows "map_of (compose xs ys) k = None"
   546 using prems by (induct xs ys rule: compose.induct)
   534 using assms by (induct xs ys rule: compose.induct)
   547   (auto split: option.splits split_if_asm)
   535   (auto split: option.splits split_if_asm)
   548 
   536 
   549 lemma compose_conv: 
   537 lemma compose_conv: 
   550   shows "map_of (compose xs ys) k = (map_of ys \<circ>\<^sub>m map_of xs) k"
   538   shows "map_of (compose xs ys) k = (map_of ys \<circ>\<^sub>m map_of xs) k"
   551 proof (induct xs ys rule: compose.induct)
   539 proof (induct xs ys rule: compose.induct)
   589   by (rule ext) (rule compose_conv)
   577   by (rule ext) (rule compose_conv)
   590 
   578 
   591 lemma compose_first_Some [simp]:
   579 lemma compose_first_Some [simp]:
   592   assumes "map_of xs k = Some v" 
   580   assumes "map_of xs k = Some v" 
   593   shows "map_of (compose xs ys) k = map_of ys v"
   581   shows "map_of (compose xs ys) k = map_of ys v"
   594 using prems by (simp add: compose_conv)
   582 using assms by (simp add: compose_conv)
   595 
   583 
   596 lemma dom_compose: "fst ` set (compose xs ys) \<subseteq> fst ` set xs"
   584 lemma dom_compose: "fst ` set (compose xs ys) \<subseteq> fst ` set xs"
   597 proof (induct xs ys rule: compose.induct)
   585 proof (induct xs ys rule: compose.induct)
   598   case 1 thus ?case by simp
   586   case 1 thus ?case by simp
   599 next
   587 next
   621 qed
   609 qed
   622 
   610 
   623 lemma distinct_compose:
   611 lemma distinct_compose:
   624  assumes "distinct (map fst xs)"
   612  assumes "distinct (map fst xs)"
   625  shows "distinct (map fst (compose xs ys))"
   613  shows "distinct (map fst (compose xs ys))"
   626 using prems
   614 using assms
   627 proof (induct xs ys rule: compose.induct)
   615 proof (induct xs ys rule: compose.induct)
   628   case 1 thus ?case by simp
   616   case 1 thus ?case by simp
   629 next
   617 next
   630   case (2 x xs ys)
   618   case (2 x xs ys)
   631   show ?case
   619   show ?case
   693   "(map_of (compose xs ys) k = None) = 
   681   "(map_of (compose xs ys) k = None) = 
   694     (map_of xs k = None \<or> (\<exists>k'. map_of xs k = Some k' \<and> map_of ys k' = None)) " 
   682     (map_of xs k = None \<or> (\<exists>k'. map_of xs k = Some k' \<and> map_of ys k' = None)) " 
   695   by (simp add: compose_conv map_comp_None_iff)
   683   by (simp add: compose_conv map_comp_None_iff)
   696 
   684 
   697 
   685 
   698 (* ******************************************************************************** *)
       
   699 subsection {* @{const restrict} *}
   686 subsection {* @{const restrict} *}
   700 (* ******************************************************************************** *)
       
   701 
   687 
   702 lemma restrict_def:
   688 lemma restrict_def:
   703   "restrict A = filter (\<lambda>p. fst p \<in> A)"
   689   "restrict A = filter (\<lambda>p. fst p \<in> A)"
   704 proof
   690 proof
   705   fix xs
   691   fix xs