lib: move wp lemmas for mapM et al into More_Monad

Signed-off-by: Gerwin Klein <gerwin.klein@proofcraft.systems>
This commit is contained in:
Gerwin Klein 2023-01-11 12:52:05 +11:00
parent d275068826
commit d86acc885a
No known key found for this signature in database
GPG Key ID: 20A847CE6AB7F5F3
2 changed files with 336 additions and 334 deletions

View File

@ -364,4 +364,310 @@ lemma mapM_x_split_append:
using mapM_x_append[where f=f and xs="take n xs" and ys="drop n xs"]
by simp
lemma mapME_wp:
assumes x: "\<And>x. x \<in> S \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>_. P\<rbrace>, \<lbrace>\<lambda>_. E\<rbrace>"
shows "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> mapME f xs \<lbrace>\<lambda>_. P\<rbrace>, \<lbrace>\<lambda>_. E\<rbrace>"
apply (induct xs)
apply (simp add: mapME_def sequenceE_def)
apply wp
apply simp
apply (simp add: mapME_Cons)
apply (wp x|simp)+
done
lemmas mapME_wp' = mapME_wp [OF _ subset_refl]
lemma mapM_x_inv_wp3:
fixes m :: "'b \<Rightarrow> ('a, unit) nondet_monad"
assumes hr: "\<And>a as bs. xs = as @ [a] @ bs \<Longrightarrow>
\<lbrace>\<lambda>s. I s \<and> V as s\<rbrace> m a \<lbrace>\<lambda>r s. I s \<and> V (as @ [a]) s\<rbrace>"
shows "\<lbrace>\<lambda>s. I s \<and> V [] s\<rbrace> mapM_x m xs \<lbrace>\<lambda>rv s. I s \<and> V xs s\<rbrace>"
using hr
proof (induct xs rule: rev_induct)
case Nil thus ?case
apply (simp add: mapM_x_Nil)
done
next
case (snoc x xs)
show ?case
apply (simp add: mapM_append_single)
apply (wp snoc.prems)
apply simp
apply (rule snoc.hyps [OF snoc.prems])
apply simp
apply assumption
done
qed
lemma mapME_x_inv_wp:
assumes x: "\<And>x. \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>rv. P\<rbrace>,\<lbrace>E\<rbrace>"
shows "\<lbrace>P\<rbrace> mapME_x f xs \<lbrace>\<lambda>rv. P\<rbrace>,\<lbrace>E\<rbrace>"
apply (induct xs)
apply (simp add: mapME_x_def sequenceE_x_def)
apply wp
apply (simp add: mapME_x_def sequenceE_x_def)
apply (fold mapME_x_def sequenceE_x_def)
apply wp
apply (rule x)
apply assumption
done
lemma mapM_upd:
assumes "\<And>x rv s s'. (rv,s') \<in> fst (f x s) \<Longrightarrow> x \<in> set xs \<Longrightarrow> (rv, g s') \<in> fst (f x (g s))"
shows "(rv,s') \<in> fst (mapM f xs s) \<Longrightarrow> (rv, g s') \<in> fst (mapM f xs (g s))"
using assms
proof (induct xs arbitrary: rv s s')
case Nil
thus ?case by (simp add: mapM_Nil return_def)
next
case (Cons z zs)
from Cons.prems
show ?case
apply (clarsimp simp: mapM_Cons in_monad)
apply (drule Cons.prems, simp)
apply (rule exI, erule conjI)
apply (erule Cons.hyps)
apply (erule Cons.prems)
apply simp
done
qed
lemma no_fail_mapM_wp:
assumes "\<And>x. x \<in> set xs \<Longrightarrow> no_fail (P x) (f x)"
assumes "\<And>x y. \<lbrakk> x \<in> set xs; y \<in> set xs \<rbrakk> \<Longrightarrow> \<lbrace>P x\<rbrace> f y \<lbrace>\<lambda>_. P x\<rbrace>"
shows "no_fail (\<lambda>s. \<forall>x \<in> set xs. P x s) (mapM f xs)"
using assms
proof (induct xs)
case Nil
thus ?case by (simp add: mapM_empty)
next
case (Cons z zs)
show ?case
apply (clarsimp simp: mapM_Cons)
apply (wp Cons.prems Cons.hyps hoare_vcg_const_Ball_lift|simp)+
done
qed
lemma no_fail_mapM:
"\<forall>x. no_fail \<top> (f x) \<Longrightarrow> no_fail \<top> (mapM f xs)"
apply (induct xs)
apply (simp add: mapM_def sequence_def)
apply (simp add: mapM_Cons)
apply (wp|fastforce)+
done
lemma filterM_preserved:
"\<lbrakk> \<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> m x \<lbrace>\<lambda>rv. P\<rbrace> \<rbrakk>
\<Longrightarrow> \<lbrace>P\<rbrace> filterM m xs \<lbrace>\<lambda>rv. P\<rbrace>"
apply (induct xs)
apply (wp | simp | erule meta_mp | drule meta_spec)+
done
lemma filterM_distinct1:
"\<lbrace>\<top> and K (P \<longrightarrow> distinct xs)\<rbrace> filterM m xs \<lbrace>\<lambda>rv s. (P \<longrightarrow> distinct rv) \<and> set rv \<subseteq> set xs\<rbrace>"
apply (rule hoare_gen_asm, erule rev_mp)
apply (rule rev_induct [where xs=xs])
apply (clarsimp | wp)+
apply (simp add: filterM_append)
apply (erule hoare_seq_ext[rotated])
apply (rule hoare_seq_ext[rotated], rule hoare_vcg_prop)
apply (wp, clarsimp)
apply blast
done
lemma filterM_subset:
"\<lbrace>\<top>\<rbrace> filterM m xs \<lbrace>\<lambda>rv s. set rv \<subseteq> set xs\<rbrace>"
by (rule hoare_chain, rule filterM_distinct1[where P=False], simp_all)
lemma filterM_all:
"\<lbrakk> \<And>x y. \<lbrakk> x \<in> set xs; y \<in> set xs \<rbrakk> \<Longrightarrow> \<lbrace>P y\<rbrace> m x \<lbrace>\<lambda>rv. P y\<rbrace> \<rbrakk> \<Longrightarrow>
\<lbrace>\<lambda>s. \<forall>x \<in> set xs. P x s\<rbrace> filterM m xs \<lbrace>\<lambda>rv s. \<forall>x \<in> set rv. P x s\<rbrace>"
apply (rule_tac Q="\<lambda>rv s. set rv \<subseteq> set xs \<and> (\<forall>x \<in> set xs. P x s)"
in hoare_strengthen_post)
apply (wp filterM_subset hoare_vcg_const_Ball_lift filterM_preserved)
apply simp+
apply blast
done
lemma filterM_distinct:
"\<lbrace>K (distinct xs)\<rbrace> filterM m xs \<lbrace>\<lambda>rv s. distinct rv\<rbrace>"
by (rule hoare_chain, rule filterM_distinct1[where P=True], simp_all)
lemma mapM_wp:
assumes x: "\<And>x. x \<in> S \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>rv. P\<rbrace>"
shows "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> mapM f xs \<lbrace>\<lambda>rv. P\<rbrace>"
apply (induct xs)
apply (simp add: mapM_def sequence_def)
apply (simp add: mapM_Cons)
apply wp
apply (rule x, clarsimp)
apply simp
done
lemma mapM_wp':
assumes x: "\<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>rv. P\<rbrace>"
shows "\<lbrace>P\<rbrace> mapM f xs \<lbrace>\<lambda>rv. P\<rbrace>"
apply (rule mapM_wp)
apply (erule x)
apply simp
done
lemma mapM_set:
assumes "\<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>_. P\<rbrace>"
assumes "\<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>_. Q x\<rbrace>"
assumes "\<And>x y. \<lbrakk> x \<in> set xs; y \<in> set xs \<rbrakk> \<Longrightarrow> \<lbrace>P and Q y\<rbrace> f x \<lbrace>\<lambda>_. Q y\<rbrace>"
shows "\<lbrace>P\<rbrace> mapM f xs \<lbrace>\<lambda>_ s. \<forall>x \<in> set xs. Q x s\<rbrace>"
using assms
proof (induct xs)
case Nil show ?case
by (simp add: mapM_def sequence_def) wp
next
case (Cons y ys)
have PQ_inv: "\<And>x. x \<in> set ys \<Longrightarrow> \<lbrace>P and Q y\<rbrace> f x \<lbrace>\<lambda>_. P and Q y\<rbrace>"
apply (simp add: pred_conj_def)
apply (rule hoare_pre)
apply (wp Cons|simp)+
done
show ?case
apply (simp add: mapM_Cons)
apply wp
apply (rule hoare_vcg_conj_lift)
apply (rule hoare_strengthen_post)
apply (rule mapM_wp')
apply (erule PQ_inv)
apply simp
apply (wp Cons|simp)+
done
qed
lemma mapM_x_wp:
assumes x: "\<And>x. x \<in> S \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>rv. P\<rbrace>"
shows "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> mapM_x f xs \<lbrace>\<lambda>rv. P\<rbrace>"
by (subst mapM_x_mapM) (wp mapM_wp x)
lemma no_fail_mapM':
assumes rl: "\<And>x. no_fail (\<lambda>_. P x) (f x)"
shows "no_fail (\<lambda>_. \<forall>x \<in> set xs. P x) (mapM f xs)"
proof (induct xs)
case Nil thus ?case by (simp add: mapM_def sequence_def)
next
case (Cons x xs)
have nf: "no_fail (\<lambda>_. P x) (f x)" by (rule rl)
have ih: "no_fail (\<lambda>_. \<forall>x \<in> set xs. P x) (mapM f xs)" by (rule Cons)
show ?case
apply (simp add: mapM_Cons)
apply (rule no_fail_pre)
apply (wp nf ih)
apply simp
done
qed
lemma det_mapM:
assumes x: "\<And>x. x \<in> S \<Longrightarrow> det (f x)"
shows "set xs \<subseteq> S \<Longrightarrow> det (mapM f xs)"
apply (induct xs)
apply (simp add: mapM_def sequence_def)
apply (simp add: mapM_Cons x)
done
lemma det_zipWithM_x:
assumes x: "\<And>x y. (x, y) \<in> set (zip xs ys) \<Longrightarrow> det (f x y)"
shows "det (zipWithM_x f xs ys)"
apply (simp add: zipWithM_x_mapM)
apply (rule bind_detI)
apply (rule det_mapM [where S="set (zip xs ys)"])
apply (clarsimp simp add: x)
apply simp
apply simp
done
lemma empty_fail_sequence_x :
assumes "\<And>m. m \<in> set ms \<Longrightarrow> empty_fail m"
shows "empty_fail (sequence_x ms)" using assms
by (induct ms) (auto simp: sequence_x_def)
lemma mapME_set:
assumes est: "\<And>x. \<lbrace>R\<rbrace> f x \<lbrace>P\<rbrace>, -"
and invp: "\<And>x y. \<lbrace>R and P x\<rbrace> f y \<lbrace>\<lambda>_. P x\<rbrace>, -"
and invr: "\<And>x. \<lbrace>R\<rbrace> f x \<lbrace>\<lambda>_. R\<rbrace>, -"
shows "\<lbrace>R\<rbrace> mapME f xs \<lbrace>\<lambda>rv s. \<forall>x \<in> set rv. P x s\<rbrace>, -"
proof (rule hoare_post_imp_R [where Q' = "\<lambda>rv s. R s \<and> (\<forall>x \<in> set rv. P x s)"], induct xs)
case Nil
thus ?case by (simp add: mapME_Nil | wp returnOKE_R_wp)+
next
case (Cons y ys)
have minvp: "\<And>x. \<lbrace>R and P x\<rbrace> mapME f ys \<lbrace>\<lambda>_. P x\<rbrace>, -"
apply (rule hoare_pre)
apply (rule_tac Q' = "\<lambda>_ s. R s \<and> P x s" in hoare_post_imp_R)
apply (wp mapME_wp' invr invp)+
apply simp
apply simp
apply simp
done
show ?case
apply (simp add: mapME_Cons)
apply (wp)
apply (rule_tac Q' = "\<lambda>xs s. (R s \<and> (\<forall>x \<in> set xs. P x s)) \<and> P x s" in hoare_post_imp_R)
apply (wp Cons.hyps minvp)
apply simp
apply (fold validE_R_def)
apply simp
apply (wp invr est)
apply simp
done
qed clarsimp
lemma empty_fail_mapM_x [simp]:
"(\<And>x. empty_fail (a x)) \<Longrightarrow> empty_fail (mapM_x a xs)"
apply (induct_tac xs)
apply (clarsimp simp: mapM_x_Nil)
apply (clarsimp simp: mapM_x_Cons)
done
lemma mapM_upd_inv:
assumes f: "\<And>x rv. (rv,s) \<in> fst (f x s) \<Longrightarrow> x \<in> set xs \<Longrightarrow> (rv, g s) \<in> fst (f x (g s))"
assumes inv: "\<And>x. \<lbrace>(=) s\<rbrace> f x \<lbrace>\<lambda>_. (=) s\<rbrace>"
shows "(rv,s) \<in> fst (mapM f xs s) \<Longrightarrow> (rv, g s) \<in> fst (mapM f xs (g s))"
using f inv
proof (induct xs arbitrary: rv s)
case Nil
thus ?case by (simp add: mapM_Nil return_def)
next
case (Cons z zs)
from Cons.prems
show ?case
apply (clarsimp simp: mapM_Cons in_monad)
apply (frule use_valid, assumption, rule refl)
apply clarsimp
apply (drule Cons.prems, simp)
apply (rule exI, erule conjI)
apply (drule Cons.hyps)
apply simp
apply assumption
apply simp
done
qed
lemma case_option_find_give_me_a_map:
"case_option a return (find f xs)
= liftM projl
(mapME (\<lambda>x. if (f x) then throwError x else returnOk ()) xs
>>=E (\<lambda>x. assert (\<forall>x \<in> set xs. \<not> f x)
>>= (\<lambda>_. liftM (Inl :: 'a \<Rightarrow> 'a + unit) a)))"
apply (induct xs)
apply simp
apply (simp add: liftM_def mapME_Nil)
apply (simp add: mapME_Cons split: if_split)
apply (clarsimp simp add: throwError_def bindE_def bind_assoc
liftM_def)
apply (rule bind_cong [OF refl])
apply (simp add: lift_def throwError_def returnOk_def split: sum.split)
done
end

View File

@ -29,20 +29,39 @@ lemma distinct_tuple_helper:
apply (simp add: map_fst_zip_prefix)
done
lemma mapME_wp:
assumes x: "\<And>x. x \<in> S \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>_. P\<rbrace>, \<lbrace>\<lambda>_. E\<rbrace>"
shows "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> mapME f xs \<lbrace>\<lambda>_. P\<rbrace>, \<lbrace>\<lambda>_. E\<rbrace>"
apply (induct xs)
apply (simp add: mapME_def sequenceE_def)
apply wp
apply simp
apply (simp add: mapME_Cons)
apply (wp x|simp)+
lemma gets_the_validE_R_wp:
"\<lbrace>\<lambda>s. f s \<noteq> None \<and> isRight (the (f s)) \<and> Q (theRight (the (f s))) s\<rbrace>
gets_the f
\<lbrace>Q\<rbrace>,-"
apply (simp add: gets_the_def validE_R_def validE_def)
apply (wp | wpc | simp add: assert_opt_def)+
apply (clarsimp split: split: sum.splits)
done
lemmas mapME_wp' = mapME_wp [OF _ subset_refl]
lemma return_bindE:
"isRight v \<Longrightarrow> return v >>=E f = f (theRight v)"
by (clarsimp simp: isRight_def return_returnOk)
lemma list_case_return: (* FIXME lib: move to Lib *)
"(case xs of [] \<Rightarrow> return v | y # ys \<Rightarrow> return (f y ys))
= return (case xs of [] \<Rightarrow> v | y # ys \<Rightarrow> f y ys)"
by (simp split: list.split)
lemma lifted_if_collapse: (* FIXME lib: move to Lib *)
"(if P then \<top> else f) = (\<lambda>s. \<not>P \<longrightarrow> f s)"
by auto
lemmas list_case_return2 = list_case_return (* FIXME lib: eliminate *)
lemma valid_isRight_theRight_split:
"\<lbrace>P\<rbrace> f \<lbrace>\<lambda>rv s. Q True rv s\<rbrace>,\<lbrace>\<lambda>e s. \<forall>v. Q False v s\<rbrace> \<Longrightarrow>
\<lbrace>P\<rbrace> f \<lbrace>\<lambda>rv s. Q (isRight rv) (theRight rv) s\<rbrace>"
apply (simp add: validE_def)
apply (erule hoare_strengthen_post)
apply (simp add: isRight_def split: sum.split_asm)
done
(* depends on Lib.list_induct_suffix *)
lemma mapM_x_inv_wp2:
assumes post: "\<And>s. \<lbrakk> I s; V [] s \<rbrakk> \<Longrightarrow> Q s"
and hr: "\<And>a as. suffix (a # as) xs \<Longrightarrow> \<lbrace>\<lambda>s. I s \<and> V (a # as) s\<rbrace> m a \<lbrace>\<lambda>r s. I s \<and> V as s\<rbrace>"
@ -63,328 +82,5 @@ next
done
qed
lemma mapM_x_inv_wp3:
fixes m :: "'b \<Rightarrow> ('a, unit) nondet_monad"
assumes hr: "\<And>a as bs. xs = as @ [a] @ bs \<Longrightarrow>
\<lbrace>\<lambda>s. I s \<and> V as s\<rbrace> m a \<lbrace>\<lambda>r s. I s \<and> V (as @ [a]) s\<rbrace>"
shows "\<lbrace>\<lambda>s. I s \<and> V [] s\<rbrace> mapM_x m xs \<lbrace>\<lambda>rv s. I s \<and> V xs s\<rbrace>"
using hr
proof (induct xs rule: rev_induct)
case Nil thus ?case
apply (simp add: mapM_x_Nil)
done
next
case (snoc x xs)
show ?case
apply (simp add: mapM_append_single)
apply (wp snoc.prems)
apply simp
apply (rule snoc.hyps [OF snoc.prems])
apply simp
apply assumption
done
qed
lemma mapME_x_inv_wp:
assumes x: "\<And>x. \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>rv. P\<rbrace>,\<lbrace>E\<rbrace>"
shows "\<lbrace>P\<rbrace> mapME_x f xs \<lbrace>\<lambda>rv. P\<rbrace>,\<lbrace>E\<rbrace>"
apply (induct xs)
apply (simp add: mapME_x_def sequenceE_x_def)
apply wp
apply (simp add: mapME_x_def sequenceE_x_def)
apply (fold mapME_x_def sequenceE_x_def)
apply wp
apply (rule x)
apply assumption
done
lemma mapM_upd:
assumes "\<And>x rv s s'. (rv,s') \<in> fst (f x s) \<Longrightarrow> x \<in> set xs \<Longrightarrow> (rv, g s') \<in> fst (f x (g s))"
shows "(rv,s') \<in> fst (mapM f xs s) \<Longrightarrow> (rv, g s') \<in> fst (mapM f xs (g s))"
using assms
proof (induct xs arbitrary: rv s s')
case Nil
thus ?case by (simp add: mapM_Nil return_def)
next
case (Cons z zs)
from Cons.prems
show ?case
apply (clarsimp simp: mapM_Cons in_monad)
apply (drule Cons.prems, simp)
apply (rule exI, erule conjI)
apply (erule Cons.hyps)
apply (erule Cons.prems)
apply simp
done
qed
lemma gets_the_validE_R_wp:
"\<lbrace>\<lambda>s. f s \<noteq> None \<and> isRight (the (f s)) \<and> Q (theRight (the (f s))) s\<rbrace>
gets_the f
\<lbrace>Q\<rbrace>,-"
apply (simp add: gets_the_def validE_R_def validE_def)
apply (wp | wpc | simp add: assert_opt_def)+
apply (clarsimp split: split: sum.splits)
done
lemma return_bindE:
"isRight v \<Longrightarrow> return v >>=E f = f (theRight v)"
by (clarsimp simp: isRight_def return_returnOk)
lemma no_fail_mapM_wp:
assumes "\<And>x. x \<in> set xs \<Longrightarrow> no_fail (P x) (f x)"
assumes "\<And>x y. \<lbrakk> x \<in> set xs; y \<in> set xs \<rbrakk> \<Longrightarrow> \<lbrace>P x\<rbrace> f y \<lbrace>\<lambda>_. P x\<rbrace>"
shows "no_fail (\<lambda>s. \<forall>x \<in> set xs. P x s) (mapM f xs)"
using assms
proof (induct xs)
case Nil
thus ?case by (simp add: mapM_empty)
next
case (Cons z zs)
show ?case
apply (clarsimp simp: mapM_Cons)
apply (wp Cons.prems Cons.hyps hoare_vcg_const_Ball_lift|simp)+
done
qed
lemma list_case_return: (* FIXME lib: move to Lib *)
"(case xs of [] \<Rightarrow> return v | y # ys \<Rightarrow> return (f y ys))
= return (case xs of [] \<Rightarrow> v | y # ys \<Rightarrow> f y ys)"
by (simp split: list.split)
lemma lifted_if_collapse: (* FIXME lib: move to Lib *)
"(if P then \<top> else f) = (\<lambda>s. \<not>P \<longrightarrow> f s)"
by auto
lemmas list_case_return2 = list_case_return (* FIXME lib: eliminate *)
lemma no_fail_mapM:
"\<forall>x. no_fail \<top> (f x) \<Longrightarrow> no_fail \<top> (mapM f xs)"
apply (induct xs)
apply (simp add: mapM_def sequence_def)
apply (simp add: mapM_Cons)
apply (wp|fastforce)+
done
lemma filterM_preserved:
"\<lbrakk> \<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> m x \<lbrace>\<lambda>rv. P\<rbrace> \<rbrakk>
\<Longrightarrow> \<lbrace>P\<rbrace> filterM m xs \<lbrace>\<lambda>rv. P\<rbrace>"
apply (induct xs)
apply (wp | simp | erule meta_mp | drule meta_spec)+
done
lemma filterM_distinct1:
"\<lbrace>\<top> and K (P \<longrightarrow> distinct xs)\<rbrace> filterM m xs \<lbrace>\<lambda>rv s. (P \<longrightarrow> distinct rv) \<and> set rv \<subseteq> set xs\<rbrace>"
apply (rule hoare_gen_asm, erule rev_mp)
apply (rule rev_induct [where xs=xs])
apply (clarsimp | wp)+
apply (simp add: filterM_append)
apply (erule hoare_seq_ext[rotated])
apply (rule hoare_seq_ext[rotated], rule hoare_vcg_prop)
apply (wp, clarsimp)
apply blast
done
lemma filterM_subset:
"\<lbrace>\<top>\<rbrace> filterM m xs \<lbrace>\<lambda>rv s. set rv \<subseteq> set xs\<rbrace>"
by (rule hoare_chain, rule filterM_distinct1[where P=False], simp_all)
lemma filterM_all:
"\<lbrakk> \<And>x y. \<lbrakk> x \<in> set xs; y \<in> set xs \<rbrakk> \<Longrightarrow> \<lbrace>P y\<rbrace> m x \<lbrace>\<lambda>rv. P y\<rbrace> \<rbrakk> \<Longrightarrow>
\<lbrace>\<lambda>s. \<forall>x \<in> set xs. P x s\<rbrace> filterM m xs \<lbrace>\<lambda>rv s. \<forall>x \<in> set rv. P x s\<rbrace>"
apply (rule_tac Q="\<lambda>rv s. set rv \<subseteq> set xs \<and> (\<forall>x \<in> set xs. P x s)"
in hoare_strengthen_post)
apply (wp filterM_subset hoare_vcg_const_Ball_lift filterM_preserved)
apply simp+
apply blast
done
lemma filterM_distinct:
"\<lbrace>K (distinct xs)\<rbrace> filterM m xs \<lbrace>\<lambda>rv s. distinct rv\<rbrace>"
by (rule hoare_chain, rule filterM_distinct1[where P=True], simp_all)
lemma mapM_wp:
assumes x: "\<And>x. x \<in> S \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>rv. P\<rbrace>"
shows "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> mapM f xs \<lbrace>\<lambda>rv. P\<rbrace>"
apply (induct xs)
apply (simp add: mapM_def sequence_def)
apply (simp add: mapM_Cons)
apply wp
apply (rule x, clarsimp)
apply simp
done
lemma mapM_wp':
assumes x: "\<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>rv. P\<rbrace>"
shows "\<lbrace>P\<rbrace> mapM f xs \<lbrace>\<lambda>rv. P\<rbrace>"
apply (rule mapM_wp)
apply (erule x)
apply simp
done
lemma mapM_set:
assumes "\<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>_. P\<rbrace>"
assumes "\<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>_. Q x\<rbrace>"
assumes "\<And>x y. \<lbrakk> x \<in> set xs; y \<in> set xs \<rbrakk> \<Longrightarrow> \<lbrace>P and Q y\<rbrace> f x \<lbrace>\<lambda>_. Q y\<rbrace>"
shows "\<lbrace>P\<rbrace> mapM f xs \<lbrace>\<lambda>_ s. \<forall>x \<in> set xs. Q x s\<rbrace>"
using assms
proof (induct xs)
case Nil show ?case
by (simp add: mapM_def sequence_def) wp
next
case (Cons y ys)
have PQ_inv: "\<And>x. x \<in> set ys \<Longrightarrow> \<lbrace>P and Q y\<rbrace> f x \<lbrace>\<lambda>_. P and Q y\<rbrace>"
apply (simp add: pred_conj_def)
apply (rule hoare_pre)
apply (wp Cons|simp)+
done
show ?case
apply (simp add: mapM_Cons)
apply wp
apply (rule hoare_vcg_conj_lift)
apply (rule hoare_strengthen_post)
apply (rule mapM_wp')
apply (erule PQ_inv)
apply simp
apply (wp Cons|simp)+
done
qed
lemma mapM_x_wp:
assumes x: "\<And>x. x \<in> S \<Longrightarrow> \<lbrace>P\<rbrace> f x \<lbrace>\<lambda>rv. P\<rbrace>"
shows "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> mapM_x f xs \<lbrace>\<lambda>rv. P\<rbrace>"
by (subst mapM_x_mapM) (wp mapM_wp x)
lemma no_fail_mapM':
assumes rl: "\<And>x. no_fail (\<lambda>_. P x) (f x)"
shows "no_fail (\<lambda>_. \<forall>x \<in> set xs. P x) (mapM f xs)"
proof (induct xs)
case Nil thus ?case by (simp add: mapM_def sequence_def)
next
case (Cons x xs)
have nf: "no_fail (\<lambda>_. P x) (f x)" by (rule rl)
have ih: "no_fail (\<lambda>_. \<forall>x \<in> set xs. P x) (mapM f xs)" by (rule Cons)
show ?case
apply (simp add: mapM_Cons)
apply (rule no_fail_pre)
apply (wp nf ih)
apply simp
done
qed
lemma det_mapM:
assumes x: "\<And>x. x \<in> S \<Longrightarrow> det (f x)"
shows "set xs \<subseteq> S \<Longrightarrow> det (mapM f xs)"
apply (induct xs)
apply (simp add: mapM_def sequence_def)
apply (simp add: mapM_Cons x)
done
lemma det_zipWithM_x:
assumes x: "\<And>x y. (x, y) \<in> set (zip xs ys) \<Longrightarrow> det (f x y)"
shows "det (zipWithM_x f xs ys)"
apply (simp add: zipWithM_x_mapM)
apply (rule bind_detI)
apply (rule det_mapM [where S="set (zip xs ys)"])
apply (clarsimp simp add: x)
apply simp
apply simp
done
lemma empty_fail_sequence_x :
assumes "\<And>m. m \<in> set ms \<Longrightarrow> empty_fail m"
shows "empty_fail (sequence_x ms)" using assms
by (induct ms) (auto simp: sequence_x_def)
lemma mapME_set:
assumes est: "\<And>x. \<lbrace>R\<rbrace> f x \<lbrace>P\<rbrace>, -"
and invp: "\<And>x y. \<lbrace>R and P x\<rbrace> f y \<lbrace>\<lambda>_. P x\<rbrace>, -"
and invr: "\<And>x. \<lbrace>R\<rbrace> f x \<lbrace>\<lambda>_. R\<rbrace>, -"
shows "\<lbrace>R\<rbrace> mapME f xs \<lbrace>\<lambda>rv s. \<forall>x \<in> set rv. P x s\<rbrace>, -"
proof (rule hoare_post_imp_R [where Q' = "\<lambda>rv s. R s \<and> (\<forall>x \<in> set rv. P x s)"], induct xs)
case Nil
thus ?case by (simp add: mapME_Nil | wp returnOKE_R_wp)+
next
case (Cons y ys)
have minvp: "\<And>x. \<lbrace>R and P x\<rbrace> mapME f ys \<lbrace>\<lambda>_. P x\<rbrace>, -"
apply (rule hoare_pre)
apply (rule_tac Q' = "\<lambda>_ s. R s \<and> P x s" in hoare_post_imp_R)
apply (wp mapME_wp' invr invp)+
apply simp
apply simp
apply simp
done
show ?case
apply (simp add: mapME_Cons)
apply (wp)
apply (rule_tac Q' = "\<lambda>xs s. (R s \<and> (\<forall>x \<in> set xs. P x s)) \<and> P x s" in hoare_post_imp_R)
apply (wp Cons.hyps minvp)
apply simp
apply (fold validE_R_def)
apply simp
apply (wp invr est)
apply simp
done
qed clarsimp
lemma empty_fail_mapM_x [simp]:
"(\<And>x. empty_fail (a x)) \<Longrightarrow> empty_fail (mapM_x a xs)"
apply (induct_tac xs)
apply (clarsimp simp: mapM_x_Nil)
apply (clarsimp simp: mapM_x_Cons)
done
lemma valid_isRight_theRight_split:
"\<lbrace>P\<rbrace> f \<lbrace>\<lambda>rv s. Q True rv s\<rbrace>,\<lbrace>\<lambda>e s. \<forall>v. Q False v s\<rbrace> \<Longrightarrow>
\<lbrace>P\<rbrace> f \<lbrace>\<lambda>rv s. Q (isRight rv) (theRight rv) s\<rbrace>"
apply (simp add: validE_def)
apply (erule hoare_strengthen_post)
apply (simp add: isRight_def split: sum.split_asm)
done
lemma mapM_upd_inv:
assumes f: "\<And>x rv. (rv,s) \<in> fst (f x s) \<Longrightarrow> x \<in> set xs \<Longrightarrow> (rv, g s) \<in> fst (f x (g s))"
assumes inv: "\<And>x. \<lbrace>(=) s\<rbrace> f x \<lbrace>\<lambda>_. (=) s\<rbrace>"
shows "(rv,s) \<in> fst (mapM f xs s) \<Longrightarrow> (rv, g s) \<in> fst (mapM f xs (g s))"
using f inv
proof (induct xs arbitrary: rv s)
case Nil
thus ?case by (simp add: mapM_Nil return_def)
next
case (Cons z zs)
from Cons.prems
show ?case
apply (clarsimp simp: mapM_Cons in_monad)
apply (frule use_valid, assumption, rule refl)
apply clarsimp
apply (drule Cons.prems, simp)
apply (rule exI, erule conjI)
apply (drule Cons.hyps)
apply simp
apply assumption
apply simp
done
qed
lemma case_option_find_give_me_a_map:
"case_option a return (find f xs)
= liftM theLeft
(mapME (\<lambda>x. if (f x) then throwError x else returnOk ()) xs
>>=E (\<lambda>x. assert (\<forall>x \<in> set xs. \<not> f x)
>>= (\<lambda>_. liftM (Inl :: 'a \<Rightarrow> 'a + unit) a)))"
apply (induct xs)
apply simp
apply (simp add: liftM_def mapME_Nil)
apply (simp add: mapME_Cons split: if_split)
apply (clarsimp simp add: throwError_def bindE_def bind_assoc
liftM_def)
apply (rule bind_cong [OF refl])
apply (simp add: lift_def throwError_def returnOk_def split: sum.split)
done
end