Theory Exc_Nres_Monad
section ‹Exception Monad for Refine-Monadic›
theory Exc_Nres_Monad
imports "Refine_Imperative_HOL.IICF"
begin
declare TrueI[refine_vcg]
type_synonym ('e,'a) enres = "('e + 'a) nres"
named_theorems enres_unfolds ‹Unfolding theorems from enres to nres›
definition [enres_unfolds]: "ERETURN x ≡ RETURN (Inr x)"
definition ebind :: "('e,'a) enres ⇒ ('a ⇒ ('e,'b) enres) ⇒ ('e,'b) enres"
where [enres_unfolds]:
"ebind m f ≡ do {
x ← m;
case x of Inl e ⇒ RETURN (Inl e) | Inr x ⇒ f x
}"
definition [enres_unfolds]: "THROW e == RETURN (Inl e)"
definition [enres_unfolds]: "ESPEC Φ Ψ ≡ SPEC (λInl e ⇒ Φ e | Inr r ⇒ Ψ r)"
definition [enres_unfolds]: "CATCH m h ≡ do { r←m; case r of Inl e ⇒ h e | Inr r ⇒ RETURN (Inr r) }"
abbreviation (do_notation) bind_doE where "bind_doE ≡ ebind"
notation (output) bind_doE (infixl ‹⤜› 54)
notation (ASCII output) bind_doE (infixl ‹>>=› 54)
nonterminal doE_binds and doE_bind
syntax
"_doE_block" :: "doE_binds ⇒ 'a" (‹doE {//(2 _)//}› [12] 62)
"_doE_bind" :: "[pttrn, 'a] ⇒ doE_bind" (‹(2_ ←/ _)› 13)
"_doE_let" :: "[pttrn, 'a] ⇒ doE_bind" (‹(2let _ =/ _)› [1000, 13] 13)
"_doE_then" :: "'a ⇒ doE_bind" (‹_› [14] 13)
"_doE_final" :: "'a ⇒ doE_binds" (‹_›)
"_doE_cons" :: "[doE_bind, doE_binds] ⇒ doE_binds" (‹_;//_› [13, 12] 12)
"_thenM" :: "['a, 'b] ⇒ 'c" (infixl ‹⪢› 54)
syntax (ASCII)
"_doE_bind" :: "[pttrn, 'a] ⇒ doE_bind" (‹(2_ <-/ _)› 13)
"_thenM" :: "['a, 'b] ⇒ 'c" (infixr ‹>>› 54)
syntax_consts
"_doE_block" "_doE_bind" "_doE_cons" "_thenM" ⇌ bind_doE and
"_doE_let" ⇌ Let
translations
"_doE_block (_doE_cons (_doE_then t) (_doE_final e))"
⇌ "CONST bind_doE t (λ_. e)"
"_doE_block (_doE_cons (_doE_bind p t) (_doE_final e))"
⇌ "CONST bind_doE t (λp. e)"
"_doE_block (_doE_cons (_doE_let p t) bs)"
⇌ "let p = t in _doE_block bs"
"_doE_block (_doE_cons b (_doE_cons c cs))"
⇌ "_doE_block (_doE_cons b (_doE_final (_doE_block (_doE_cons c cs))))"
"_doE_cons (_doE_let p t) (_doE_final s)"
⇌ "_doE_final (let p = t in s)"
"_doE_block (_doE_final e)" ⇀ "e"
"(m ⪢ n)" ⇀ "(m ⤜ (λ_. n))"
definition [enres_unfolds]: "CHECK Φ e ≡ if Φ then ERETURN () else THROW e"
definition [enres_unfolds]: "EASSUME Φ ≡ if Φ then ERETURN () else SUCCEED"
definition [enres_unfolds]: "EASSERT Φ ≡ if Φ then ERETURN () else FAIL"
lemma EASSUME_simps[simp]:
"EASSUME True = ERETURN ()"
"EASSUME False = SUCCEED"
unfolding EASSUME_def by auto
lemma EASSERT_simps[simp]:
"EASSERT True = ERETURN ()"
"EASSERT False = FAIL"
unfolding EASSERT_def by auto
lemma CHECK_simps[simp]:
"CHECK True e = ERETURN ()"
"CHECK False e = THROW e"
unfolding CHECK_def by auto
lemma pw_ESPEC[simp, refine_pw_simps]:
"nofail (ESPEC Φ Ψ)"
"inres (ESPEC Φ Ψ) (Inl e) ⟷ Φ e"
"inres (ESPEC Φ Ψ) (Inr x) ⟷ Ψ x"
unfolding enres_unfolds
by auto
lemma pw_ERETURN[simp, refine_pw_simps]:
"nofail (ERETURN x)"
"¬inres (ERETURN x) (Inl e)"
"inres (ERETURN x) (Inr y) ⟷ x=y"
unfolding enres_unfolds
by auto
lemma pw_ebind[refine_pw_simps]:
"nofail (ebind m f) ⟷ nofail m ∧ (∀x. inres m (Inr x) ⟶ nofail (f x))"
"inres (ebind m f) (Inl e) ⟷ inres m (Inl e) ∨ (∃x. inres m (Inr x) ∧ inres (f x) (Inl e))"
"inres (ebind m f) (Inr x) ⟷ nofail m ⟶ (∃y. inres m (Inr y) ∧ inres (f y) (Inr x))"
unfolding enres_unfolds
apply (auto simp: refine_pw_simps split: sum.split)
using sum.exhaust_sel apply blast
using sum.exhaust_sel apply blast
done
lemma pw_THROW[simp,refine_pw_simps]:
"nofail (THROW e)"
"inres (THROW e) (Inl f) ⟷ f=e"
"¬inres (THROW e) (Inr x)"
unfolding enres_unfolds
by (auto simp: refine_pw_simps)
lemma pw_CHECK[simp, refine_pw_simps]:
"nofail (CHECK Φ e)"
"inres (CHECK Φ e) (Inl f) ⟷ ¬Φ ∧ f=e"
"inres (CHECK Φ e) (Inr u) ⟷ Φ"
unfolding enres_unfolds
by (auto simp: refine_pw_simps)
lemma pw_EASSUME[simp, refine_pw_simps]:
"nofail (EASSUME Φ)"
"¬inres (EASSUME Φ) (Inl e)"
"inres (EASSUME Φ) (Inr u) ⟷ Φ"
unfolding EASSUME_def
by (auto simp: refine_pw_simps)
lemma pw_EASSERT[simp, refine_pw_simps]:
"nofail (EASSERT Φ) ⟷ Φ"
"inres (EASSERT Φ) (Inr u)"
"inres (EASSERT Φ) (Inl e) ⟷ ¬Φ"
unfolding EASSERT_def
by (auto simp: refine_pw_simps)
lemma pw_CATCH[refine_pw_simps]:
"nofail (CATCH m h) ⟷ (nofail m ∧ (∀x. inres m (Inl x) ⟶ nofail (h x)))"
"inres (CATCH m h) (Inl e) ⟷ (nofail m ⟶ (∃e'. inres m (Inl e') ∧ inres (h e') (Inl e)))"
"inres (CATCH m h) (Inr x) ⟷ inres m (Inr x) ∨ (∃e. inres m (Inl e) ∧ inres (h e) (Inr x))"
unfolding CATCH_def
apply (auto simp add: refine_pw_simps split: sum.splits)
using sum.exhaust_sel apply blast
using sum.exhaust_sel apply blast
done
lemma pw_ele_iff: "m ≤ n ⟷ (nofail n ⟶
nofail m
∧ (∀e. inres m (Inl e) ⟶ inres n (Inl e))
∧ (∀x. inres m (Inr x) ⟶ inres n (Inr x))
)"
apply (auto simp: pw_le_iff)
by (metis sum.exhaust_sel)
lemma pw_eeq_iff: "m = n ⟷
(nofail m ⟷ nofail n)
∧ (∀e. inres m (Inl e) ⟷ inres n (Inl e))
∧ (∀x. inres m (Inr x) ⟷ inres n (Inr x))"
apply (auto simp: pw_eq_iff)
by (metis sum.exhaust_sel)+
lemma enres_monad_laws[simp]:
"ebind (ERETURN x) f = f x"
"ebind m (ERETURN) = m"
"ebind (ebind m f) g = ebind m (λx. ebind (f x) g)"
by (auto simp: pw_eeq_iff refine_pw_simps)
lemma enres_additional_laws[simp]:
"ebind (THROW e) f = THROW e"
"CATCH (THROW e) h = h e"
"CATCH (ERETURN x) h = ERETURN x"
"CATCH m THROW = m"
apply (auto simp: pw_eeq_iff refine_pw_simps)
done
lemmas ESPEC_trans = order_trans[where z="ESPEC Error_Postcond Normal_Postcond" for Error_Postcond Normal_Postcond, zero_var_indexes]
lemma ESPEC_cons:
assumes "m ≤ ESPEC E Q"
assumes "⋀e. E e ⟹ E' e"
assumes "⋀x. Q x ⟹ Q' x"
shows "m ≤ ESPEC E' Q'"
using assms by (auto simp: pw_ele_iff)
lemma ebind_rule_iff: "doE { x←m; f x } ≤ ESPEC Φ Ψ ⟷ m ≤ ESPEC Φ (λx. f x ≤ ESPEC Φ Ψ)"
by (auto simp: pw_ele_iff refine_pw_simps)
lemmas ebind_rule[refine_vcg] = ebind_rule_iff[THEN iffD2]
lemma ERETURN_rule_iff[simp]: "ERETURN x ≤ ESPEC Φ Ψ ⟷ Ψ x"
by (auto simp: pw_ele_iff refine_pw_simps)
lemmas ERETURN_rule[refine_vcg] = ERETURN_rule_iff[THEN iffD2]
lemma ESPEC_rule_iff: "ESPEC Φ Ψ ≤ ESPEC Φ' Ψ' ⟷ (∀e. Φ e ⟶ Φ' e) ∧ (∀x. Ψ x ⟶ Ψ' x)"
by (auto simp: pw_ele_iff refine_pw_simps)
lemmas ESPEC_rule[refine_vcg] = ESPEC_rule_iff[THEN iffD2]
lemma THROW_rule_iff: "THROW e ≤ ESPEC Φ Ψ ⟷ Φ e"
by (auto simp: pw_ele_iff refine_pw_simps)
lemmas THROW_rule[refine_vcg] = THROW_rule_iff[THEN iffD2]
lemma CATCH_rule_iff: "CATCH m h ≤ ESPEC Φ Ψ ⟷ m ≤ ESPEC (λe. h e ≤ ESPEC Φ Ψ) Ψ"
by (auto simp: pw_ele_iff refine_pw_simps)
lemmas CATCH_rule[refine_vcg] = CATCH_rule_iff[THEN iffD2]
lemma CHECK_rule_iff: "CHECK c e ≤ ESPEC Φ Ψ ⟷ (c ⟶ Ψ ()) ∧ (¬c ⟶ Φ e)"
by (auto simp: pw_ele_iff refine_pw_simps)
lemma CHECK_rule[refine_vcg]:
assumes "c ⟹ Ψ ()"
assumes "¬c ⟹ Φ e"
shows "CHECK c e ≤ ESPEC Φ Ψ"
using assms by (simp add: CHECK_rule_iff)
lemma EASSUME_rule[refine_vcg]: "⟦Φ ⟹ Ψ ()⟧ ⟹ EASSUME Φ ≤ ESPEC E Ψ"
by (cases Φ) auto
lemma EASSERT_rule[refine_vcg]: "⟦Φ; Φ ⟹ Ψ ()⟧ ⟹ EASSERT Φ ≤ ESPEC E Ψ" by auto
lemma eprod_rule[refine_vcg]:
"⟦⋀a b. p=(a,b) ⟹ S a b ≤ ESPEC Φ Ψ⟧ ⟹ (case p of (a,b) ⇒ S a b) ≤ ESPEC Φ Ψ"
by (auto split: prod.split)
lemma eprod2_rule[refine_vcg]:
assumes "⋀a b c d. ⟦ab=(a,b); cd=(c,d)⟧ ⟹ f a b c d ≤ ESPEC Φ Ψ"
shows "(λ(a,b) (c,d). f a b c d) ab cd ≤ ESPEC Φ Ψ"
using assms
by (auto split: prod.split)
lemma eif_rule[refine_vcg]:
"⟦ b ⟹ S1 ≤ ESPEC Φ Ψ; ¬b ⟹ S2 ≤ ESPEC Φ Ψ⟧
⟹ (if b then S1 else S2) ≤ ESPEC Φ Ψ"
by (auto)
lemma eoption_rule[refine_vcg]:
"⟦ v=None ⟹ S1 ≤ ESPEC Φ Ψ; ⋀x. v=Some x ⟹ f2 x ≤ ESPEC Φ Ψ⟧
⟹ case_option S1 f2 v ≤ ESPEC Φ Ψ"
by (auto split: option.split)
lemma eLet_rule[refine_vcg]: "f v ≤ ESPEC Φ Ψ ⟹ (let x=v in f x) ≤ ESPEC Φ Ψ" by simp
lemma eLet_rule':
assumes "⋀x. x=v ⟹ f x ≤ ESPEC Φ Ψ"
shows "Let v (λx. f x) ≤ ESPEC Φ Ψ"
using assms by simp
definition [enres_unfolds]: "EWHILEIT I c f s ≡ WHILEIT
(λInl _ ⇒ True | Inr s ⇒ I s)
(λInl _ ⇒ False | Inr s ⇒ c s)
(λs. ASSERT (¬isl s) ⪢ (let s = projr s in f s))
(Inr s)"
definition [enres_unfolds]: "EWHILET ≡ EWHILEIT (λ_. True)"
lemma EWHILEIT_rule[refine_vcg]:
assumes WF: "wf R"
and I0: "I s⇩0"
and IS: "⋀s. ⟦I s; b s; (s,s⇩0)∈R⇧*⟧ ⟹ f s ≤ ESPEC E (λs'. I s' ∧ (s', s) ∈ R)"
and IMP: "⋀s. ⟦I s; ¬ b s; (s,s⇩0)∈R⇧*⟧ ⟹ Φ s"
shows "EWHILEIT I b f s⇩0 ≤ ESPEC E Φ"
unfolding EWHILEIT_def ESPEC_def
apply (rule order_trans[OF WHILEIT_weaken[where I="λInl e ⇒ E e | Inr s ⇒ I s ∧ (s,s⇩0)∈R⇧*"]])
apply (auto split: sum.splits) []
apply (rule WHILEIT_rule[where R="inv_image (less_than <*lex*> R) (λInl e ⇒ (0,undefined) | Inr s ⇒ (1,s))"])
subgoal using WF by auto
subgoal using I0 by auto
subgoal
apply (clarsimp split: sum.splits simp: ESPEC_def)
apply (rule order_trans[OF IS])
apply (auto simp: ESPEC_def)
done
subgoal using IMP by (auto split: sum.splits)
done
lemma EWHILET_rule:
assumes WF: "wf R"
and I0: "I s⇩0"
and IS: "⋀s. ⟦I s; b s; (s,s⇩0)∈R⇧*⟧ ⟹ f s ≤ ESPEC E (λs'. I s' ∧ (s', s) ∈ R)"
and IMP: "⋀s. ⟦I s; ¬ b s; (s,s⇩0)∈R⇧*⟧ ⟹ Φ s"
shows "EWHILET b f s⇩0 ≤ ESPEC E Φ"
unfolding EWHILET_def EWHILEIT_def ESPEC_def
apply (rule order_trans[OF WHILEIT_weaken[where I="λInl e ⇒ E e | Inr s ⇒ I s ∧ (s,s⇩0)∈R⇧*"]])
apply (auto split: sum.splits) []
apply (rule WHILEIT_rule[where R="inv_image (less_than <*lex*> R) (λInl e ⇒ (0,undefined) | Inr s ⇒ (1,s))"])
subgoal using WF by auto
subgoal using I0 by auto
subgoal
apply (clarsimp split: sum.splits simp: ESPEC_def)
apply (rule order_trans[OF IS])
apply (auto simp: ESPEC_def)
done
subgoal using IMP by (auto split: sum.splits)
done
lemma EWHILEIT_weaken:
assumes "⋀x. I x ⟹ I' x"
shows "EWHILEIT I' b f x ≤ EWHILEIT I b f x"
unfolding enres_unfolds
apply (rule WHILEIT_weaken)
using assms by (auto split: sum.split)
text ‹Explicitly specify a different invariant. ›
lemma EWHILEIT_expinv_rule:
assumes WF: "wf R"
and I0: "I s⇩0"
and IS: "⋀s. ⟦I s; b s; (s,s⇩0)∈R⇧*⟧ ⟹ f s ≤ ESPEC E (λs'. I s' ∧ (s', s) ∈ R)"
and IMP: "⋀s. ⟦I s; ¬ b s; (s,s⇩0)∈R⇧*⟧ ⟹ Φ s"
and INVIMP: "⋀s. I s ⟹ I' s"
shows "EWHILEIT I' b f s⇩0 ≤ ESPEC E Φ"
apply (rule order_trans[OF EWHILEIT_weaken])
using INVIMP apply assumption
apply (rule EWHILEIT_rule; fact+)
done
definition [enres_unfolds]: "enfoldli l c f s ≡
nfoldli l (λInl e⇒False | Inr x ⇒ c x) (λx s. do {ASSERT (¬isl s); let s=projr s; f x s}) (Inr s)"
lemma enfoldli_simps[simp]:
"enfoldli [] c f s = ERETURN s"
"enfoldli (x#ls) c f s =
(if c s then doE { s←f x s; enfoldli ls c f s} else ERETURN s)"
unfolding enres_unfolds
by (auto split: sum.split intro!: arg_cong[where f = "Refine_Basic.bind _"] ext)
lemma enfoldli_rule:
assumes I0: "I [] l0 σ0"
assumes IS: "⋀x l1 l2 σ. ⟦ l0=l1@x#l2; I l1 (x#l2) σ; c σ ⟧ ⟹ f x σ ≤ ESPEC E (I (l1@[x]) l2)"
assumes FNC: "⋀l1 l2 σ. ⟦ l0=l1@l2; I l1 l2 σ; ¬c σ ⟧ ⟹ P σ"
assumes FC: "⋀σ. ⟦ I l0 [] σ; c σ ⟧ ⟹ P σ"
shows "enfoldli l0 c f σ0 ≤ ESPEC E P"
unfolding enfoldli_def ESPEC_def
apply (rule nfoldli_rule[where I="λl1 l2. λInl e ⇒ E e | Inr σ ⇒ I l1 l2 σ"])
subgoal by (auto simp: I0)
subgoal
apply (simp split: sum.splits)
apply (erule (2) order_trans[OF IS])
apply (auto simp: ESPEC_def)
done
subgoal using FNC by (auto split: sum.split)
subgoal using FC by (auto split: sum.split)
done
subsection ‹Data Refinement›
lemma sum_rel_conv:
"(Inl l, s') ∈ ⟨L,R⟩sum_rel ⟷ (∃l'. s'=Inl l' ∧ (l,l')∈L)"
"(Inr r, s') ∈ ⟨L,R⟩sum_rel ⟷ (∃r'. s'=Inr r' ∧ (r,r')∈R)"
"(s, Inl l') ∈ ⟨L,R⟩sum_rel ⟷ (∃l. s=Inl l ∧ (l,l')∈L)"
"(s, Inr r') ∈ ⟨L,R⟩sum_rel ⟷ (∃r. s=Inr r ∧ (r,r')∈R)"
"(∀l. s ≠ Inl l) ⟷ (∃r. s=Inr r)"
"(∀r. s ≠ Inr r) ⟷ (∃l. s=Inl l)"
apply -
subgoal by (cases s'; auto)
subgoal by (cases s'; auto)
subgoal by (cases s; auto)
subgoal by (cases s; auto)
subgoal by (cases s; auto)
subgoal by (cases s; auto)
done
definition econc_fun (‹⇓⇩E›) where [enres_unfolds]: "econc_fun E R ≡ ⇓(⟨E,R⟩sum_rel)"
lemma RELATES_pat_erefine[refine_dref_pattern]: "⟦RELATES R; mi ≤⇓⇩E E R m ⟧ ⟹ mi ≤⇓⇩E E R m" .
lemma pw_econc_iff[refine_pw_simps]:
"inres (⇓⇩E E R m) (Inl ei) ⟷ (nofail m ⟶ (∃e. inres m (Inl e) ∧ (ei,e)∈E))"
"inres (⇓⇩E E R m) (Inr xi) ⟷ (nofail m ⟶ (∃x. inres m (Inr x) ∧ (xi,x)∈R))"
"nofail (⇓⇩E E R m) ⟷ nofail m"
by (auto simp: refine_pw_simps econc_fun_def sum_rel_conv)
lemma econc_fun_id[simp]: "⇓⇩E Id Id = (λx. x)"
by (auto simp: pw_eeq_iff refine_pw_simps intro!: ext)
lemma econc_fun_ESPEC: "⇓⇩E E R (ESPEC Φ Ψ) = ESPEC (λei. ∃e. (ei,e)∈E ∧ Φ e) (λri. ∃r. (ri,r)∈R ∧ Ψ r)"
by (auto simp: pw_eeq_iff refine_pw_simps)
lemma econc_fun_ERETURN: "⇓⇩E E R (ERETURN x) = ESPEC (λ_. False) (λxi. (xi,x)∈R)"
by (auto simp: pw_eeq_iff refine_pw_simps)
lemma econc_fun_univ_id[simp]: "⇓⇩E UNIV Id (ESPEC Φ Ψ) = ESPEC (λ_. Ex Φ) Ψ"
by (auto simp: pw_eeq_iff refine_pw_simps)
lemma erefine_same_sup_Id[simp]: "⟦ Id⊆E; Id⊆R ⟧ ⟹ m ≤⇓⇩E E R m" by (auto simp: pw_ele_iff refine_pw_simps)
lemma econc_mono3: "m≤m' ⟹ ⇓⇩E E R m ≤ ⇓⇩E E R m'"
by (auto simp: pw_ele_iff refine_pw_simps)
lemma econc_x_trans[trans]:
"x ≤ ⇓⇩E E R y ⟹ y ≤ z ⟹ x ≤ ⇓⇩E E R z"
by (force simp: pw_ele_iff refine_pw_simps)
lemma econc_econc_trans[trans]:
"x ≤⇓⇩E E1 R1 y ⟹ y ≤ ⇓⇩E E2 R2 z ⟹ x ≤ ⇓⇩E (E1 O E2) (R1 O R2) z"
by (force simp: pw_ele_iff refine_pw_simps)
lemma ERETURN_refine[refine]:
assumes "(xi,x)∈R"
shows "ERETURN xi ≤ ⇓⇩EE R (ERETURN x)"
using assms
by (auto simp: pw_ele_iff refine_pw_simps)
lemma EASSERT_bind_refine_right:
assumes "Φ ⟹ mi ≤⇓⇩E E R m"
shows "mi ≤⇓⇩E E R (doE {EASSERT Φ; m})"
using assms
by (simp add: pw_ele_iff refine_pw_simps)
lemma EASSERT_bind_refine_left:
assumes "Φ"
assumes "mi ≤⇓⇩E E R m"
shows "(doE {EASSERT Φ; mi}) ≤⇓⇩E E R m"
using assms
by simp
lemma EASSUME_bind_refine_right:
assumes "Φ"
assumes "mi ≤⇓⇩E E R m"
shows "mi ≤⇓⇩E E R (doE {EASSUME Φ; m})"
using assms
by (simp)
lemma EASSUME_bind_refine_left:
assumes "Φ ⟹ mi ≤⇓⇩E E R m"
shows "(doE {EASSUME Φ; mi}) ≤⇓⇩E E R m"
using assms
by (simp add: pw_ele_iff refine_pw_simps)
lemma ebind_refine:
assumes "mi ≤⇓⇩E E R' m"
assumes "⋀xi x. (xi,x)∈R' ⟹ fi xi ≤⇓⇩E E R (f x)"
shows "doE { xi ← mi; fi xi } ≤ ⇓⇩E E R (doE { x ← m; f x })"
using assms
by (simp add: pw_ele_iff refine_pw_simps) blast
text ‹Order of this lemmas matters!›
lemmas [refine] =
ebind_refine
EASSERT_bind_refine_left EASSUME_bind_refine_right
EASSUME_bind_refine_left EASSERT_bind_refine_right
thm refine(1-10)
lemma ebind_refine':
assumes "mi ≤⇓⇩E E R' m"
assumes "⋀xi x. ⟦(xi,x)∈R'; inres mi (Inr xi); inres m (Inr x); nofail mi; nofail m⟧ ⟹ fi xi ≤⇓⇩E E R (f x)"
shows "doE { xi ← mi; fi xi } ≤ ⇓⇩E E R (doE { x ← m; f x })"
using assms
by (simp add: pw_ele_iff refine_pw_simps) blast
lemma THROW_refine[refine]: "(ei,e)∈E ⟹ THROW ei ≤⇓⇩E E R (THROW e)"
by (auto simp: pw_ele_iff refine_pw_simps)
lemma CATCH_refine':
assumes "mi ≤ ⇓⇩E E' R m"
assumes "⋀ei e. ⟦ (ei,e)∈E'; inres mi (Inl ei); inres m (Inl e); nofail mi; nofail m ⟧ ⟹ hi ei ≤⇓⇩E E R (h e)"
shows "CATCH mi hi ≤ ⇓⇩E E R (CATCH m h)"
using assms
by (simp add: pw_ele_iff refine_pw_simps) blast
lemma CATCH_refine[refine]:
assumes "mi ≤ ⇓⇩E E' R m"
assumes "⋀ei e. ⟦ (ei,e)∈E' ⟧ ⟹ hi ei ≤⇓⇩E E R (h e)"
shows "CATCH mi hi ≤ ⇓⇩E E R (CATCH m h)"
using assms CATCH_refine' by metis
lemma CHECK_refine[refine]:
assumes "Φi ⟷ Φ"
assumes "¬Φ ⟹ (msgi,msg)∈E"
shows "CHECK Φi msgi ≤⇓⇩E E Id (CHECK Φ msg)"
using assms by (auto simp: pw_ele_iff refine_pw_simps)
text ‹This must be declared after @{thm CHECK_refine}!›
lemma CHECK_bind_refine[refine]:
assumes "Φi ⟷ Φ"
assumes "¬Φ ⟹ (msgi,msg)∈E"
assumes "Φ ⟹ mi ≤⇓⇩E E R m"
shows "doE {CHECK Φi msgi;mi} ≤⇓⇩E E R (doE {CHECK Φ msg; m})"
using assms by (auto simp: pw_ele_iff refine_pw_simps)
lemma Let_unfold_refine[refine]:
assumes "f x ≤ ⇓⇩E E R (f' x')"
shows "Let x f ≤ ⇓⇩E E R (Let x' f')"
using assms by auto
lemma Let_refine:
assumes "(m,m')∈R'"
assumes "⋀x x'. (x,x')∈R' ⟹ f x ≤ ⇓⇩E E R (f' x')"
shows "Let m (λx. f x) ≤⇓⇩E E R (Let m' (λx'. f' x'))"
using assms by auto
lemma eif_refine[refine]:
assumes "(b,b')∈bool_rel"
assumes "⟦b;b'⟧ ⟹ S1 ≤ ⇓⇩E E R S1'"
assumes "⟦¬b;¬b'⟧ ⟹ S2 ≤ ⇓⇩E E R S2'"
shows "(if b then S1 else S2) ≤ ⇓⇩E E R (if b' then S1' else S2')"
using assms by auto
lemma enfoldli_refine[refine]:
assumes "(li, l) ∈ ⟨S⟩list_rel"
and "(si, s) ∈ R"
and CR: "(ci, c) ∈ R → bool_rel"
and FR: "⋀xi x si s. ⟦ (xi,x)∈S; (si,s)∈R; c s ⟧ ⟹ fi xi si ≤ ⇓⇩E E R (f x s)"
shows "enfoldli li ci fi si ≤ ⇓⇩E E R (enfoldli l c f s)"
unfolding enres_unfolds
apply (rule nfoldli_refine)
apply (rule assms(1))
apply (simp add: assms(2))
subgoal using CR[param_fo] by (auto split: sum.split simp: sum_rel_conv)
subgoal
apply refine_rcg
applyS (auto split: sum.splits simp: sum_rel_conv)
apply (rule FR[unfolded enres_unfolds])
by (auto split: sum.splits simp: sum_rel_conv)
done
lemma EWHILET_refine[refine]:
assumes R0: "(x,x')∈R"
assumes COND_REF: "⋀x x'. ⟦ (x,x')∈R ⟧ ⟹ b x = b' x'"
assumes STEP_REF:
"⋀x x'. ⟦ (x,x')∈R; b x; b' x' ⟧ ⟹ f x ≤ ⇓⇩E E R (f' x')"
shows "EWHILET b f x ≤⇓⇩E E R (EWHILET b' f' x')"
unfolding enres_unfolds
apply refine_rcg
using assms
by (auto split: sum.splits simp: econc_fun_def)
thm WHILEIT_refine
lemma EWHILEIT_refine[refine]:
assumes R0: "I' x' ⟹ (x,x')∈R"
assumes I_REF: "⋀x x'. ⟦ (x,x')∈R; I' x' ⟧ ⟹ I x"
assumes COND_REF: "⋀x x'. ⟦ (x,x')∈R; I x; I' x' ⟧ ⟹ b x = b' x'"
assumes STEP_REF:
"⋀x x'. ⟦ (x,x')∈R; b x; b' x'; I x; I' x' ⟧ ⟹ f x ≤ ⇓⇩E E R (f' x')"
shows "EWHILEIT I b f x ≤⇓⇩E E R (EWHILEIT I' b' f' x')"
unfolding enres_unfolds
apply refine_rcg
using assms
by (auto split: sum.splits simp: econc_fun_def)
subsubsection ‹Refine2- heuristics›
lemma remove_eLet_refine:
assumes "M ≤ ⇓⇩E E R (f x)"
shows "M ≤ ⇓⇩E E R (Let x f)" using assms by auto
lemma intro_eLet_refine:
assumes "f x ≤ ⇓⇩E E R M'"
shows "Let x f ≤ ⇓⇩E E R M'" using assms by auto
lemma ebind2let_refine[refine2]:
assumes "ERETURN x ≤ ⇓⇩E E R' M'"
assumes "⋀x'. (x,x')∈R' ⟹ f x ≤ ⇓⇩E E R (f' x')"
shows "Let x f ≤ ⇓⇩E E R (ebind M' (λx'. f' x'))"
using assms
apply (simp add: pw_ele_iff refine_pw_simps)
apply fast
done
lemma ebind_Let_refine2[refine2]: "⟦
m' ≤⇓⇩E E R' (ERETURN x);
⋀x'. ⟦inres m' (Inr x'); (x',x)∈R'⟧ ⟹ f' x' ≤ ⇓⇩E E R (f x)
⟧ ⟹ ebind m' (λx'. f' x') ≤ ⇓⇩E E R (Let x (λx. f x))"
apply (simp add: pw_ele_iff refine_pw_simps)
apply blast
done
lemma ebind2letRETURN_refine[refine2]:
assumes "ERETURN x ≤ ⇓⇩E E R' M'"
assumes "⋀x'. (x,x')∈R' ⟹ ERETURN (f x) ≤ ⇓⇩E E R (f' x')"
shows "ERETURN (Let x f) ≤ ⇓⇩E E R (ebind M' (λx'. f' x'))"
using assms
apply (simp add: pw_ele_iff refine_pw_simps)
apply fast
done
lemma ERETURN_as_SPEC_refine[refine2]:
assumes "RELATES R"
assumes "M ≤ ESPEC (λ_. False) (λc. (c,a)∈R)"
shows "M ≤ ⇓⇩E E R (ERETURN a)"
using assms
by (simp add: pw_ele_iff refine_pw_simps)
lemma if_ERETURN_refine[refine2]:
assumes "b ⟷ b'"
assumes "⟦b;b'⟧ ⟹ ERETURN S1 ≤ ⇓⇩E E R S1'"
assumes "⟦¬b;¬b'⟧ ⟹ ERETURN S2 ≤ ⇓⇩E E R S2'"
shows "ERETURN (if b then S1 else S2) ≤ ⇓⇩E E R (if b' then S1' else S2')"
using assms
by (simp add: pw_le_iff refine_pw_simps)
text ‹Breaking down enres-monad ›
definition enres_lift :: "'a nres ⇒ (_,'a) enres" where
"enres_lift m ≡ do { x ← m; RETURN (Inr x) }"
lemma enres_lift_rule[refine_vcg]: "m≤SPEC Φ ⟹ enres_lift m ≤ ESPEC E Φ"
by (auto simp: pw_ele_iff pw_le_iff refine_pw_simps enres_lift_def)
named_theorems_rev enres_breakdown
lemma [enres_breakdown]:
"ERETURN x = enres_lift (RETURN x)"
"EASSERT Φ = enres_lift (ASSERT Φ)"
"doE { x ← enres_lift m; ef x } = do { x ← m; ef x }"
unfolding enres_unfolds enres_lift_def
apply (auto split: sum.splits simp: pw_eq_iff refine_pw_simps)
done
lemma [enres_breakdown]:
"do { x ← m; enres_lift (f x) } = enres_lift (do { x ← m; f x })"
"do { let x = v; enres_lift (f x) } = enres_lift (do { let x=v; f x })"
unfolding enres_unfolds enres_lift_def
apply (auto split: sum.splits simp: pw_eq_iff refine_pw_simps)
done
lemma [enres_breakdown]:
"CATCH (enres_lift m) h = enres_lift m"
unfolding enres_unfolds enres_lift_def
apply (auto split: sum.splits simp: pw_eq_iff refine_pw_simps)
done
lemma enres_lift_fail[simp]: "enres_lift FAIL = FAIL"
unfolding enres_lift_def by auto
lemma [enres_breakdown]: "EWHILEIT I c (λs. enres_lift (f s)) s = enres_lift (WHILEIT I c f s)"
(is "?lhs = ?rhs")
proof (rule antisym)
show "?lhs ≤ ?rhs"
unfolding enres_unfolds WHILEIT_def WHILET_def
apply (rule RECT_transfer_rel'[where P="λc a. c = Inr a"])
apply (simp add: while.WHILEI_body_trimono)
apply (simp add: while.WHILEI_body_trimono)
apply simp
apply simp
by (auto simp: WHILEI_body_def enres_lift_def pw_le_iff refine_pw_simps)
show "?rhs ≤ ?lhs"
unfolding enres_unfolds WHILEIT_def WHILET_def
apply (rule RECT_transfer_rel'[where P="λa c. c = Inr a"])
apply (simp add: while.WHILEI_body_trimono)
apply (simp add: while.WHILEI_body_trimono)
apply simp
apply simp
by (auto simp: WHILEI_body_def enres_lift_def pw_le_iff refine_pw_simps)
qed
lemma [enres_breakdown]: "EWHILET c (λs. enres_lift (f s)) s = enres_lift (WHILET c f s)"
unfolding EWHILET_def WHILET_def enres_breakdown ..
lemma [enres_breakdown]: "enfoldli l c (λx s. enres_lift (f x s)) s = enres_lift (nfoldli l c f s)"
apply (induction l arbitrary: s)
by (auto simp: enres_breakdown)
lemma [enres_breakdown]:
"(λ(a,b). enres_lift (f a b)) = (λx. enres_lift (case x of (a,b) ⇒ f a b))" by auto
lemmas [enres_breakdown] = nres_monad_laws nres_bind_let_law
lemma [enres_breakdown]:
"doE { CHECK Φ e; m } = (if Φ then m else THROW e)"
by (auto simp: enres_unfolds)
lemma [enres_breakdown]: "(if b then enres_lift m else enres_lift n) = enres_lift (if b then m else n)"
by simp
lemma option_case_enbd[enres_breakdown]:
"case_option (enres_lift fn) (λv. enres_lift (fs v)) = (λx. enres_lift (case_option fn fs x))"
by (auto split: option.split)
named_theorems enres_inline
method opt_enres_unfold = ((unfold enres_inline)?; (unfold enres_monad_laws)?; (unfold enres_breakdown)?; (rule refl)?; (unfold enres_unfolds enres_lift_def nres_monad_laws)?; (rule refl)?)
subsection ‹More Combinators›
subsubsection ‹CHECK-Monadic›
definition [enres_unfolds]: "CHECK_monadic c e ≡ doE { b ← c; CHECK b e }"
lemma CHECK_monadic_rule_iff:
"(CHECK_monadic c e ≤ ESPEC E P) ⟷ (c ≤ ESPEC E (λr. (r ⟶ P ()) ∧ (¬r ⟶ E e)))"
by (auto simp: pw_ele_iff CHECK_monadic_def refine_pw_simps)
lemma CHECK_monadic_pw[refine_pw_simps]:
"nofail (CHECK_monadic c e) ⟷ nofail c"
"inres (CHECK_monadic c e) (Inl ee) ⟷ (inres c (Inl ee) ∨ inres c (Inr False) ∧ ee=e)"
"inres (CHECK_monadic c e) (Inr x) ⟷ (inres c (Inr True))"
unfolding CHECK_monadic_def
by (auto simp: refine_pw_simps)
lemma CHECK_monadic_rule[refine_vcg]:
assumes "c ≤ ESPEC E (λr. (r ⟶ P ()) ∧ (¬r ⟶ E e))"
shows "CHECK_monadic c e ≤ ESPEC E P"
using assms by (simp add: CHECK_monadic_rule_iff)
lemma CHECK_monadic_refine[refine]:
assumes "ci ≤ ⇓⇩E ER bool_rel c"
assumes "(ei,e)∈ER"
shows "CHECK_monadic ci ei ≤⇓⇩E ER unit_rel (CHECK_monadic c e)"
using assms
by (auto simp: pw_ele_iff refine_pw_simps)
lemma CHECK_monadic_CHECK_refine[refine]:
assumes "ci ≤ ESPEC (λe'. (e',e)∈ER ∧ ¬c) (λr. r ⟷ c)"
assumes "(ei,e)∈ER"
shows "CHECK_monadic ci ei ≤⇓⇩E ER unit_rel (CHECK c e)"
using assms
by (auto simp: pw_ele_iff refine_pw_simps)
lemma CHECK_monadic_endb[enres_breakdown]: "CHECK_monadic (enres_lift c) e =
do {b ← c; CHECK b e}"
by (auto simp: enres_unfolds enres_lift_def)
end