37 subsection {* Elimination rules for basic monadic commands *} |
37 subsection {* Elimination rules for basic monadic commands *} |
38 |
38 |
39 lemma crelE[consumes 1]: |
39 lemma crelE[consumes 1]: |
40 assumes "crel (f >>= g) h h'' r'" |
40 assumes "crel (f >>= g) h h'' r'" |
41 obtains h' r where "crel f h h' r" "crel (g r) h' h'' r'" |
41 obtains h' r where "crel f h h' r" "crel (g r) h' h'' r'" |
42 using assms by (auto simp add: crel_def bindM_def split: option.split_asm) |
42 using assms by (auto simp add: crel_def bind_def split: option.split_asm) |
43 |
43 |
44 lemma crelE'[consumes 1]: |
44 lemma crelE'[consumes 1]: |
45 assumes "crel (f >> g) h h'' r'" |
45 assumes "crel (f >> g) h h'' r'" |
46 obtains h' r where "crel f h h' r" "crel g h' h'' r'" |
46 obtains h' r where "crel f h h' r" "crel g h' h'' r'" |
47 using assms |
47 using assms |
71 obtains "x = None" "crel n h h' r" |
71 obtains "x = None" "crel n h h' r" |
72 | y where "x = Some y" "crel (s y) h h' r" |
72 | y where "x = Some y" "crel (s y) h h' r" |
73 using assms |
73 using assms |
74 unfolding crel_def by auto |
74 unfolding crel_def by auto |
75 |
75 |
76 lemma crel_mapM: |
76 lemma crel_fold_map: |
77 assumes "crel (mapM f xs) h h' r" |
77 assumes "crel (Heap_Monad.fold_map f xs) h h' r" |
78 assumes "\<And>h h'. P f [] h h' []" |
78 assumes "\<And>h h'. P f [] h h' []" |
79 assumes "\<And>h h1 h' x xs y ys. \<lbrakk> crel (f x) h h1 y; crel (mapM f xs) h1 h' ys; P f xs h1 h' ys \<rbrakk> \<Longrightarrow> P f (x#xs) h h' (y#ys)" |
79 assumes "\<And>h h1 h' x xs y ys. \<lbrakk> crel (f x) h h1 y; crel (Heap_Monad.fold_map f xs) h1 h' ys; P f xs h1 h' ys \<rbrakk> \<Longrightarrow> P f (x#xs) h h' (y#ys)" |
80 shows "P f xs h h' r" |
80 shows "P f xs h h' r" |
81 using assms(1) |
81 using assms(1) |
82 proof (induct xs arbitrary: h h' r) |
82 proof (induct xs arbitrary: h h' r) |
83 case Nil with assms(2) show ?case |
83 case Nil with assms(2) show ?case |
84 by (auto elim: crel_return) |
84 by (auto elim: crel_return) |
85 next |
85 next |
86 case (Cons x xs) |
86 case (Cons x xs) |
87 from Cons(2) obtain h1 y ys where crel_f: "crel (f x) h h1 y" |
87 from Cons(2) obtain h1 y ys where crel_f: "crel (f x) h h1 y" |
88 and crel_mapM: "crel (mapM f xs) h1 h' ys" |
88 and crel_fold_map: "crel (Heap_Monad.fold_map f xs) h1 h' ys" |
89 and r_def: "r = y#ys" |
89 and r_def: "r = y#ys" |
90 unfolding mapM.simps |
90 unfolding fold_map.simps |
91 by (auto elim!: crelE crel_return) |
91 by (auto elim!: crelE crel_return) |
92 from Cons(1)[OF crel_mapM] crel_mapM crel_f assms(3) r_def |
92 from Cons(1)[OF crel_fold_map] crel_fold_map crel_f assms(3) r_def |
93 show ?case by auto |
93 show ?case by auto |
94 qed |
94 qed |
95 |
95 |
96 |
96 |
97 subsection {* Elimination rules for array commands *} |
97 subsection {* Elimination rules for array commands *} |
154 from assms have l: "b - Suc a < b" by arith |
154 from assms have l: "b - Suc a < b" by arith |
155 from assms have "Suc (b - Suc a) = b - a" by arith |
155 from assms have "Suc (b - Suc a) = b - a" by arith |
156 with l show ?thesis by (simp add: upt_conv_Cons) |
156 with l show ?thesis by (simp add: upt_conv_Cons) |
157 qed |
157 qed |
158 |
158 |
159 lemma crel_mapM_nth: |
159 lemma crel_fold_map_nth: |
160 assumes |
160 assumes |
161 "crel (mapM (Array.nth a) [Array.length a h - n..<Array.length a h]) h h' xs" |
161 "crel (Heap_Monad.fold_map (Array.nth a) [Array.length a h - n..<Array.length a h]) h h' xs" |
162 assumes "n \<le> Array.length a h" |
162 assumes "n \<le> Array.length a h" |
163 shows "h = h' \<and> xs = drop (Array.length a h - n) (get_array a h)" |
163 shows "h = h' \<and> xs = drop (Array.length a h - n) (get_array a h)" |
164 using assms |
164 using assms |
165 proof (induct n arbitrary: xs h h') |
165 proof (induct n arbitrary: xs h h') |
166 case 0 thus ?case |
166 case 0 thus ?case |
168 next |
168 next |
169 case (Suc n) |
169 case (Suc n) |
170 from Suc(3) have "[Array.length a h - Suc n..<Array.length a h] = (Array.length a h - Suc n)#[Array.length a h - n..<Array.length a h]" |
170 from Suc(3) have "[Array.length a h - Suc n..<Array.length a h] = (Array.length a h - Suc n)#[Array.length a h - n..<Array.length a h]" |
171 by (simp add: upt_conv_Cons') |
171 by (simp add: upt_conv_Cons') |
172 with Suc(2) obtain r where |
172 with Suc(2) obtain r where |
173 crel_mapM: "crel (mapM (Array.nth a) [Array.length a h - n..<Array.length a h]) h h' r" |
173 crel_fold_map: "crel (Heap_Monad.fold_map (Array.nth a) [Array.length a h - n..<Array.length a h]) h h' r" |
174 and xs_def: "xs = get_array a h ! (Array.length a h - Suc n) # r" |
174 and xs_def: "xs = get_array a h ! (Array.length a h - Suc n) # r" |
175 by (auto elim!: crelE crel_nth crel_return) |
175 by (auto elim!: crelE crel_nth crel_return) |
176 from Suc(3) have "Array.length a h - n = Suc (Array.length a h - Suc n)" |
176 from Suc(3) have "Array.length a h - n = Suc (Array.length a h - Suc n)" |
177 by arith |
177 by arith |
178 with Suc.hyps[OF crel_mapM] xs_def show ?case |
178 with Suc.hyps[OF crel_fold_map] xs_def show ?case |
179 unfolding Array.length_def |
179 unfolding Array.length_def |
180 by (auto simp add: nth_drop') |
180 by (auto simp add: nth_drop') |
181 qed |
181 qed |
182 |
182 |
183 lemma crel_freeze: |
183 lemma crel_freeze: |
184 assumes "crel (Array.freeze a) h h' xs" |
184 assumes "crel (Array.freeze a) h h' xs" |
185 obtains "h = h'" "xs = get_array a h" |
185 obtains "h = h'" "xs = get_array a h" |
186 using assms unfolding freeze_def |
186 using assms unfolding freeze_def |
187 by (elim crel_heap) simp |
187 by (elim crel_heap) simp |
188 |
188 |
189 lemma crel_mapM_map_entry_remains: |
189 lemma crel_fold_map_map_entry_remains: |
190 assumes "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) h h' r" |
190 assumes "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) h h' r" |
191 assumes "i < Array.length a h - n" |
191 assumes "i < Array.length a h - n" |
192 shows "get_array a h ! i = get_array a h' ! i" |
192 shows "get_array a h ! i = get_array a h' ! i" |
193 using assms |
193 using assms |
194 proof (induct n arbitrary: h h' r) |
194 proof (induct n arbitrary: h h' r) |
195 case 0 |
195 case 0 |
199 case (Suc n) |
199 case (Suc n) |
200 let ?h1 = "Array.change a (Array.length a h - Suc n) (f (get_array a h ! (Array.length a h - Suc n))) h" |
200 let ?h1 = "Array.change a (Array.length a h - Suc n) (f (get_array a h ! (Array.length a h - Suc n))) h" |
201 from Suc(3) have "[Array.length a h - Suc n..<Array.length a h] = (Array.length a h - Suc n)#[Array.length a h - n..<Array.length a h]" |
201 from Suc(3) have "[Array.length a h - Suc n..<Array.length a h] = (Array.length a h - Suc n)#[Array.length a h - n..<Array.length a h]" |
202 by (simp add: upt_conv_Cons') |
202 by (simp add: upt_conv_Cons') |
203 from Suc(2) this obtain r where |
203 from Suc(2) this obtain r where |
204 crel_mapM: "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) ?h1 h' r" |
204 crel_fold_map: "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) ?h1 h' r" |
205 by (auto simp add: elim!: crelE crel_map_entry crel_return) |
205 by (auto simp add: elim!: crelE crel_map_entry crel_return) |
206 have length_remains: "Array.length a ?h1 = Array.length a h" by simp |
206 have length_remains: "Array.length a ?h1 = Array.length a h" by simp |
207 from crel_mapM have crel_mapM': "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a ?h1 - n..<Array.length a ?h1]) ?h1 h' r" |
207 from crel_fold_map have crel_fold_map': "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a ?h1 - n..<Array.length a ?h1]) ?h1 h' r" |
208 by simp |
208 by simp |
209 from Suc(1)[OF this] length_remains Suc(3) show ?case by simp |
209 from Suc(1)[OF this] length_remains Suc(3) show ?case by simp |
210 qed |
210 qed |
211 |
211 |
212 lemma crel_mapM_map_entry_changes: |
212 lemma crel_fold_map_map_entry_changes: |
213 assumes "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) h h' r" |
213 assumes "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) h h' r" |
214 assumes "n \<le> Array.length a h" |
214 assumes "n \<le> Array.length a h" |
215 assumes "i \<ge> Array.length a h - n" |
215 assumes "i \<ge> Array.length a h - n" |
216 assumes "i < Array.length a h" |
216 assumes "i < Array.length a h" |
217 shows "get_array a h' ! i = f (get_array a h ! i)" |
217 shows "get_array a h' ! i = f (get_array a h ! i)" |
218 using assms |
218 using assms |
224 case (Suc n) |
224 case (Suc n) |
225 let ?h1 = "Array.change a (Array.length a h - Suc n) (f (get_array a h ! (Array.length a h - Suc n))) h" |
225 let ?h1 = "Array.change a (Array.length a h - Suc n) (f (get_array a h ! (Array.length a h - Suc n))) h" |
226 from Suc(3) have "[Array.length a h - Suc n..<Array.length a h] = (Array.length a h - Suc n)#[Array.length a h - n..<Array.length a h]" |
226 from Suc(3) have "[Array.length a h - Suc n..<Array.length a h] = (Array.length a h - Suc n)#[Array.length a h - n..<Array.length a h]" |
227 by (simp add: upt_conv_Cons') |
227 by (simp add: upt_conv_Cons') |
228 from Suc(2) this obtain r where |
228 from Suc(2) this obtain r where |
229 crel_mapM: "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) ?h1 h' r" |
229 crel_fold_map: "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) ?h1 h' r" |
230 by (auto simp add: elim!: crelE crel_map_entry crel_return) |
230 by (auto simp add: elim!: crelE crel_map_entry crel_return) |
231 have length_remains: "Array.length a ?h1 = Array.length a h" by simp |
231 have length_remains: "Array.length a ?h1 = Array.length a h" by simp |
232 from Suc(3) have less: "Array.length a h - Suc n < Array.length a h - n" by arith |
232 from Suc(3) have less: "Array.length a h - Suc n < Array.length a h - n" by arith |
233 from Suc(3) have less2: "Array.length a h - Suc n < Array.length a h" by arith |
233 from Suc(3) have less2: "Array.length a h - Suc n < Array.length a h" by arith |
234 from Suc(4) length_remains have cases: "i = Array.length a ?h1 - Suc n \<or> i \<ge> Array.length a ?h1 - n" by arith |
234 from Suc(4) length_remains have cases: "i = Array.length a ?h1 - Suc n \<or> i \<ge> Array.length a ?h1 - n" by arith |
235 from crel_mapM have crel_mapM': "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a ?h1 - n..<Array.length a ?h1]) ?h1 h' r" |
235 from crel_fold_map have crel_fold_map': "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a ?h1 - n..<Array.length a ?h1]) ?h1 h' r" |
236 by simp |
236 by simp |
237 from Suc(1)[OF this] cases Suc(3) Suc(5) length_remains |
237 from Suc(1)[OF this] cases Suc(3) Suc(5) length_remains |
238 crel_mapM_map_entry_remains[OF this, of "Array.length a h - Suc n", symmetric] less less2 |
238 crel_fold_map_map_entry_remains[OF this, of "Array.length a h - Suc n", symmetric] less less2 |
239 show ?case |
239 show ?case |
240 by (auto simp add: nth_list_update_eq Array.length_def) |
240 by (auto simp add: nth_list_update_eq Array.length_def) |
241 qed |
241 qed |
242 |
242 |
243 lemma crel_mapM_map_entry_length: |
243 lemma crel_fold_map_map_entry_length: |
244 assumes "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) h h' r" |
244 assumes "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) h h' r" |
245 assumes "n \<le> Array.length a h" |
245 assumes "n \<le> Array.length a h" |
246 shows "Array.length a h' = Array.length a h" |
246 shows "Array.length a h' = Array.length a h" |
247 using assms |
247 using assms |
248 proof (induct n arbitrary: h h' r) |
248 proof (induct n arbitrary: h h' r) |
249 case 0 |
249 case 0 |
252 case (Suc n) |
252 case (Suc n) |
253 let ?h1 = "Array.change a (Array.length a h - Suc n) (f (get_array a h ! (Array.length a h - Suc n))) h" |
253 let ?h1 = "Array.change a (Array.length a h - Suc n) (f (get_array a h ! (Array.length a h - Suc n))) h" |
254 from Suc(3) have "[Array.length a h - Suc n..<Array.length a h] = (Array.length a h - Suc n)#[Array.length a h - n..<Array.length a h]" |
254 from Suc(3) have "[Array.length a h - Suc n..<Array.length a h] = (Array.length a h - Suc n)#[Array.length a h - n..<Array.length a h]" |
255 by (simp add: upt_conv_Cons') |
255 by (simp add: upt_conv_Cons') |
256 from Suc(2) this obtain r where |
256 from Suc(2) this obtain r where |
257 crel_mapM: "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) ?h1 h' r" |
257 crel_fold_map: "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) ?h1 h' r" |
258 by (auto elim!: crelE crel_map_entry crel_return) |
258 by (auto elim!: crelE crel_map_entry crel_return) |
259 have length_remains: "Array.length a ?h1 = Array.length a h" by simp |
259 have length_remains: "Array.length a ?h1 = Array.length a h" by simp |
260 from crel_mapM have crel_mapM': "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a ?h1 - n..<Array.length a ?h1]) ?h1 h' r" |
260 from crel_fold_map have crel_fold_map': "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a ?h1 - n..<Array.length a ?h1]) ?h1 h' r" |
261 by simp |
261 by simp |
262 from Suc(1)[OF this] length_remains Suc(3) show ?case by simp |
262 from Suc(1)[OF this] length_remains Suc(3) show ?case by simp |
263 qed |
263 qed |
264 |
264 |
265 lemma crel_mapM_map_entry: |
265 lemma crel_fold_map_map_entry: |
266 assumes "crel (mapM (\<lambda>n. map_entry n f a) [0..<Array.length a h]) h h' r" |
266 assumes "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [0..<Array.length a h]) h h' r" |
267 shows "get_array a h' = List.map f (get_array a h)" |
267 shows "get_array a h' = List.map f (get_array a h)" |
268 proof - |
268 proof - |
269 from assms have "crel (mapM (\<lambda>n. map_entry n f a) [Array.length a h - Array.length a h..<Array.length a h]) h h' r" by simp |
269 from assms have "crel (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a h - Array.length a h..<Array.length a h]) h h' r" by simp |
270 from crel_mapM_map_entry_length[OF this] |
270 from crel_fold_map_map_entry_length[OF this] |
271 crel_mapM_map_entry_changes[OF this] show ?thesis |
271 crel_fold_map_map_entry_changes[OF this] show ?thesis |
272 unfolding Array.length_def |
272 unfolding Array.length_def |
273 by (auto intro: nth_equalityI) |
273 by (auto intro: nth_equalityI) |
274 qed |
274 qed |
275 |
275 |
276 |
276 |
340 using assms |
340 using assms |
341 unfolding assert_def |
341 unfolding assert_def |
342 by (elim crel_if crel_return crel_raise) auto |
342 by (elim crel_if crel_return crel_raise) auto |
343 |
343 |
344 lemma crel_assert_eq: "(\<And>h h' r. crel f h h' r \<Longrightarrow> P r) \<Longrightarrow> f \<guillemotright>= assert P = f" |
344 lemma crel_assert_eq: "(\<And>h h' r. crel f h h' r \<Longrightarrow> P r) \<Longrightarrow> f \<guillemotright>= assert P = f" |
345 unfolding crel_def bindM_def Let_def assert_def |
345 unfolding crel_def bind_def Let_def assert_def |
346 raise_def return_def prod_case_beta |
346 raise_def return_def prod_case_beta |
347 apply (cases f) |
347 apply (cases f) |
348 apply simp |
348 apply simp |
349 apply (simp add: expand_fun_eq split_def) |
349 apply (simp add: expand_fun_eq split_def) |
350 apply (auto split: option.split) |
350 apply (auto split: option.split) |
357 subsection {* Introduction rules for basic monadic commands *} |
357 subsection {* Introduction rules for basic monadic commands *} |
358 |
358 |
359 lemma crelI: |
359 lemma crelI: |
360 assumes "crel f h h' r" "crel (g r) h' h'' r'" |
360 assumes "crel f h h' r" "crel (g r) h' h'' r'" |
361 shows "crel (f >>= g) h h'' r'" |
361 shows "crel (f >>= g) h h'' r'" |
362 using assms by (simp add: crel_def' bindM_def) |
362 using assms by (simp add: crel_def' bind_def) |
363 |
363 |
364 lemma crelI': |
364 lemma crelI': |
365 assumes "crel f h h' r" "crel g h' h'' r'" |
365 assumes "crel f h h' r" "crel g h' h'' r'" |
366 shows "crel (f >> g) h h'' r'" |
366 shows "crel (f >> g) h h'' r'" |
367 using assms by (intro crelI) auto |
367 using assms by (intro crelI) auto |
511 lemma noErrorI: |
511 lemma noErrorI: |
512 assumes "noError f h" |
512 assumes "noError f h" |
513 assumes "\<And>h' r. crel f h h' r \<Longrightarrow> noError (g r) h'" |
513 assumes "\<And>h' r. crel f h h' r \<Longrightarrow> noError (g r) h'" |
514 shows "noError (f \<guillemotright>= g) h" |
514 shows "noError (f \<guillemotright>= g) h" |
515 using assms |
515 using assms |
516 by (auto simp add: noError_def' crel_def' bindM_def) |
516 by (auto simp add: noError_def' crel_def' bind_def) |
517 |
517 |
518 lemma noErrorI': |
518 lemma noErrorI': |
519 assumes "noError f h" |
519 assumes "noError f h" |
520 assumes "\<And>h' r. crel f h h' r \<Longrightarrow> noError g h'" |
520 assumes "\<And>h' r. crel f h h' r \<Longrightarrow> noError g h'" |
521 shows "noError (f \<guillemotright> g) h" |
521 shows "noError (f \<guillemotright> g) h" |
522 using assms |
522 using assms |
523 by (auto simp add: noError_def' crel_def' bindM_def) |
523 by (auto simp add: noError_def' crel_def' bind_def) |
524 |
524 |
525 lemma noErrorI2: |
525 lemma noErrorI2: |
526 "\<lbrakk>crel f h h' r ; noError f h; noError (g r) h'\<rbrakk> |
526 "\<lbrakk>crel f h h' r ; noError f h; noError (g r) h'\<rbrakk> |
527 \<Longrightarrow> noError (f \<guillemotright>= g) h" |
527 \<Longrightarrow> noError (f \<guillemotright>= g) h" |
528 by (auto simp add: noError_def' crel_def' bindM_def) |
528 by (auto simp add: noError_def' crel_def' bind_def) |
529 |
529 |
530 lemma noError_return: |
530 lemma noError_return: |
531 shows "noError (return x) h" |
531 shows "noError (return x) h" |
532 unfolding noError_def return_def |
532 unfolding noError_def return_def |
533 by auto |
533 by auto |
544 assumes "noError n h" |
544 assumes "noError n h" |
545 shows "noError (case x of None \<Rightarrow> n | Some y \<Rightarrow> s y) h" |
545 shows "noError (case x of None \<Rightarrow> n | Some y \<Rightarrow> s y) h" |
546 using assms |
546 using assms |
547 by (auto split: option.split) |
547 by (auto split: option.split) |
548 |
548 |
549 lemma noError_mapM: |
549 lemma noError_fold_map: |
550 assumes "\<forall>x \<in> set xs. noError (f x) h \<and> crel (f x) h h (r x)" |
550 assumes "\<forall>x \<in> set xs. noError (f x) h \<and> crel (f x) h h (r x)" |
551 shows "noError (mapM f xs) h" |
551 shows "noError (Heap_Monad.fold_map f xs) h" |
552 using assms |
552 using assms |
553 proof (induct xs) |
553 proof (induct xs) |
554 case Nil |
554 case Nil |
555 thus ?case |
555 thus ?case |
556 unfolding mapM.simps by (intro noError_return) |
556 unfolding fold_map.simps by (intro noError_return) |
557 next |
557 next |
558 case (Cons x xs) |
558 case (Cons x xs) |
559 thus ?case |
559 thus ?case |
560 unfolding mapM.simps |
560 unfolding fold_map.simps |
561 by (auto intro: noErrorI2[of "f x"] noErrorI noError_return) |
561 by (auto intro: noErrorI2[of "f x"] noErrorI noError_return) |
562 qed |
562 qed |
563 |
563 |
564 lemma noError_heap [simp]: |
564 lemma noError_heap [simp]: |
565 "noError (Heap_Monad.heap f) h" |
565 "noError (Heap_Monad.heap f) h" |
609 |
609 |
610 lemma noError_freeze: |
610 lemma noError_freeze: |
611 "noError (freeze a) h" |
611 "noError (freeze a) h" |
612 by (simp add: freeze_def) |
612 by (simp add: freeze_def) |
613 |
613 |
614 lemma noError_mapM_map_entry: |
614 lemma noError_fold_map_map_entry: |
615 assumes "n \<le> Array.length a h" |
615 assumes "n \<le> Array.length a h" |
616 shows "noError (mapM (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) h" |
616 shows "noError (Heap_Monad.fold_map (\<lambda>n. map_entry n f a) [Array.length a h - n..<Array.length a h]) h" |
617 using assms |
617 using assms |
618 proof (induct n arbitrary: h) |
618 proof (induct n arbitrary: h) |
619 case 0 |
619 case 0 |
620 thus ?case by (auto intro: noError_return) |
620 thus ?case by (auto intro: noError_return) |
621 next |
621 next |