65 lift_definition union :: "('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt" is "rbt_union" |
65 lift_definition union :: "('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt" is "rbt_union" |
66 by (simp add: rbt_union_is_rbt) |
66 by (simp add: rbt_union_is_rbt) |
67 |
67 |
68 lift_definition foldi :: "('c \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'b \<Rightarrow> 'c \<Rightarrow> 'c) \<Rightarrow> ('a :: linorder, 'b) rbt \<Rightarrow> 'c \<Rightarrow> 'c" |
68 lift_definition foldi :: "('c \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'b \<Rightarrow> 'c \<Rightarrow> 'c) \<Rightarrow> ('a :: linorder, 'b) rbt \<Rightarrow> 'c \<Rightarrow> 'c" |
69 is RBT_Impl.foldi . |
69 is RBT_Impl.foldi . |
|
70 |
|
71 lift_definition combine_with_key :: "('a \<Rightarrow> 'b \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> ('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt" |
|
72 is RBT_Impl.rbt_union_with_key by (rule is_rbt_rbt_unionwk) |
|
73 |
|
74 lift_definition combine :: "('b \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> ('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt" |
|
75 is RBT_Impl.rbt_union_with by (rule rbt_unionw_is_rbt) |
70 |
76 |
71 subsection \<open>Derived operations\<close> |
77 subsection \<open>Derived operations\<close> |
72 |
78 |
73 definition is_empty :: "('a::linorder, 'b) rbt \<Rightarrow> bool" where |
79 definition is_empty :: "('a::linorder, 'b) rbt \<Rightarrow> bool" where |
74 [code]: "is_empty t = (case impl_of t of RBT_Impl.Empty \<Rightarrow> True | _ \<Rightarrow> False)" |
80 [code]: "is_empty t = (case impl_of t of RBT_Impl.Empty \<Rightarrow> True | _ \<Rightarrow> False)" |
75 |
81 |
|
82 (* TODO: Is deleting more efficient than re-building the tree? |
|
83 (Probably more difficult to prove though *) |
|
84 definition filter :: "('a \<Rightarrow> 'b \<Rightarrow> bool) \<Rightarrow> ('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt" where |
|
85 [code]: "filter P t = fold (\<lambda>k v t. if P k v then insert k v t else t) t empty" |
76 |
86 |
77 subsection \<open>Abstract lookup properties\<close> |
87 subsection \<open>Abstract lookup properties\<close> |
78 |
88 |
79 lemma lookup_RBT: |
89 lemma lookup_RBT: |
80 "is_rbt t \<Longrightarrow> lookup (RBT t) = rbt_lookup t" |
90 "is_rbt t \<Longrightarrow> lookup (RBT t) = rbt_lookup t" |
126 |
136 |
127 lemma lookup_map [simp]: |
137 lemma lookup_map [simp]: |
128 "lookup (map f t) k = map_option (f k) (lookup t k)" |
138 "lookup (map f t) k = map_option (f k) (lookup t k)" |
129 by transfer (rule rbt_lookup_map) |
139 by transfer (rule rbt_lookup_map) |
130 |
140 |
|
141 lemma lookup_combine_with_key [simp]: |
|
142 "lookup (combine_with_key f t1 t2) k = combine_options (f k) (lookup t1 k) (lookup t2 k)" |
|
143 by transfer (simp_all add: combine_options_def rbt_lookup_rbt_unionwk) |
|
144 |
|
145 lemma combine_altdef: "combine f t1 t2 = combine_with_key (\<lambda>_. f) t1 t2" |
|
146 by transfer (simp add: rbt_union_with_def) |
|
147 |
|
148 lemma lookup_combine [simp]: |
|
149 "lookup (combine f t1 t2) k = combine_options f (lookup t1 k) (lookup t2 k)" |
|
150 by (simp add: combine_altdef) |
|
151 |
131 lemma fold_fold: |
152 lemma fold_fold: |
132 "fold f t = List.fold (case_prod f) (entries t)" |
153 "fold f t = List.fold (case_prod f) (entries t)" |
133 by transfer (rule RBT_Impl.fold_def) |
154 by transfer (rule RBT_Impl.fold_def) |
134 |
155 |
135 lemma impl_of_empty: |
156 lemma impl_of_empty: |
179 by transfer (simp add: non_empty_rbt_keys) |
200 by transfer (simp add: non_empty_rbt_keys) |
180 |
201 |
181 lemma keys_def_alt: |
202 lemma keys_def_alt: |
182 "keys t = List.map fst (entries t)" |
203 "keys t = List.map fst (entries t)" |
183 by transfer (simp add: RBT_Impl.keys_def) |
204 by transfer (simp add: RBT_Impl.keys_def) |
|
205 |
|
206 context |
|
207 begin |
|
208 |
|
209 private lemma lookup_filter_aux: |
|
210 assumes "distinct (List.map fst xs)" |
|
211 shows "lookup (List.fold (\<lambda>(k, v) t. if P k v then insert k v t else t) xs t) k = |
|
212 (case map_of xs k of |
|
213 None \<Rightarrow> lookup t k |
|
214 | Some v \<Rightarrow> if P k v then Some v else lookup t k)" |
|
215 using assms by (induction xs arbitrary: t) (force split: option.splits)+ |
|
216 |
|
217 lemma lookup_filter: |
|
218 "lookup (filter P t) k = |
|
219 (case lookup t k of None \<Rightarrow> None | Some v \<Rightarrow> if P k v then Some v else None)" |
|
220 unfolding filter_def using lookup_filter_aux[of "entries t" P empty k] |
|
221 by (simp add: fold_fold distinct_entries split: option.splits) |
|
222 |
|
223 end |
|
224 |
184 |
225 |
185 subsection \<open>Quickcheck generators\<close> |
226 subsection \<open>Quickcheck generators\<close> |
186 |
227 |
187 quickcheck_generator rbt predicate: is_rbt constructors: empty, insert |
228 quickcheck_generator rbt predicate: is_rbt constructors: empty, insert |
188 |
229 |