src/HOL/Imperative_HOL/Relational.thy
changeset 37756 59caa6180fff
parent 37755 7086b7feaaa5
child 37758 bf86a65403a8
equal deleted inserted replaced
37755:7086b7feaaa5 37756:59caa6180fff
    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