lemma Heap_cases [case_names succeed fail]: fixes f and h assumes succeed: "∧x h'. execute f h = Some (x, h') ==> P" assumes fail: "execute f h = None ==> P" shows P using assms by (cases "execute f h") auto
lemma Heap_eqI: "(∧h. execute f h = execute g h) ==> f = g" by (cases f, cases g) (auto simp: fun_eq_iff)
named_theorems execute_simps "simplification rules for execute"
lemma execute_Let [execute_simps]: "execute (let x = t in f x) = (let x = t in execute (f x))" by (simp add: Let_def)
subsubsection ‹Specialised lifters›
definition tap :: "(heap ==> 'a) ==> 'a Heap"where
[code del]: "tap f = Heap (λh. Some (f h, h))"
lemma execute_tap [execute_simps]: "execute (tap f) h = Some (f h, h)" by (simp add: tap_def)
definition heap :: "(heap ==> 'a × heap) ==> 'a Heap"where
[code del]: "heap f = Heap (Some ∘ f)"
lemma execute_heap [execute_simps]: "execute (heap f) = Some ∘ f" by (simp add: heap_def)
definition guard :: "(heap ==> bool) ==> (heap ==> 'a × heap) ==> 'a Heap"where
[code del]: "guard P f = Heap (λh. if P h then Some (f h) else None)"
lemma execute_guard [execute_simps]: "¬ P h ==> execute (guard P f) h = None" "P h ==> execute (guard P f) h = Some (f h)" by (simp_all add: guard_def)
lemma success_guardI [success_intros]: "P h ==> success (guard P f) h" by (rule successI) (simp add: execute_guard)
lemma success_LetI [success_intros]: "x = t ==> success (f x) h ==> success (let x = t in f x) h" by (simp add: Let_def)
lemma success_ifI: "(c ==> success t h) ==> (¬ c ==> success e h) ==> success (if c then t else e) h" by (simp add: success_def)
subsubsection ‹Predicate for a simple relational calculus›
text‹ The ‹effect›predicate states that when a computation ‹c› runs with the heap ‹h›will result in return value ‹r› and a heap ‹h'›, i.e.~no exception occurs. ›
definition effect :: "'a Heap ==> heap ==> heap ==> 'a ==> bool"where
effect_def: "effect c h h' r ⟷ execute c h = Some (r, h')"
lemma effectI: "execute c h = Some (r, h') ==> effect c h h' r" by (simp add: effect_def)
lemma effectE: assumes"effect c h h' r" obtains"r = fst (the (execute c h))" and"h' = snd (the (execute c h))" and"success c h" proof (rule that) from assms have *: "execute c h = Some (r, h')"by (simp add: effect_def) thenshow"success c h"by (simp add: success_def) from * have"fst (the (execute c h)) = r"and"snd (the (execute c h)) = h'" by simp_all thenshow"r = fst (the (execute c h))" and"h' = snd (the (execute c h))"by simp_all qed
lemma effect_success: "effect c h h' r ==> success c h" by (simp add: effect_def success_def)
lemma success_effectE: assumes"success c h" obtains r h' where"effect c h h' r" using assms by (auto simp add: effect_def success_def)
lemma effect_deterministic: assumes"effect f h h' a" and"effect f h h'' b" shows"a = b"and"h' = h''" using assms unfolding effect_def by auto
named_theorems effect_intros "introduction rules for effect" and effect_elims "elimination rules for effect"
lemma effect_LetI [effect_intros]: assumes"x = t""effect (f x) h h' r" shows"effect (let x = t in f x) h h' r" using assms by simp
lemma effect_LetE [effect_elims]: assumes"effect (let x = t in f x) h h' r" obtains"effect (f t) h h' r" using assms by simp
lemma effect_ifI: assumes"c ==> effect t h h' r" and"¬ c ==> effect e h h' r" shows"effect (if c then t else e) h h' r" by (cases c) (simp_all add: assms)
lemma effect_ifE: assumes"effect (if c then t else e) h h' r" obtains"c""effect t h h' r"
| "¬ c""effect e h h' r" using assms by (cases c) simp_all
lemma effect_tapI [effect_intros]: assumes"h' = h""r = f h" shows"effect (tap f) h h' r" by (rule effectI) (simp add: assms execute_simps)
lemma effect_tapE [effect_elims]: assumes"effect (tap f) h h' r" obtains"h' = h"and"r = f h" using assms by (rule effectE) (auto simp add: execute_simps)
lemma execute_bind [execute_simps]: "execute f h = Some (x, h') ==> execute (f 🍋 g) h = execute (g x) h'" "execute f h = None ==> execute (f 🍋 g) h = None" by (simp_all add: bind_def)
lemma execute_bind_case: "execute (f 🍋 g) h = (case (execute f h) of Some (x, h') ==> execute (g x) h' | None ==> None)" by (simp add: bind_def)
lemma execute_bind_success: "success f h ==> execute (f 🍋 g) h = execute (g (fst (the (execute f h)))) (snd (the (execute f h)))" by (cases f h rule: Heap_cases) (auto elim: successE simp add: bind_def)
lemma success_bind_executeI: "execute f h = Some (x, h') ==> success (g x) h' ==> success (f 🍋 g) h" by (auto intro!: successI elim: successE simp add: bind_def)
lemma success_bind_effectI [success_intros]: "effect f h h' x ==> success (g x) h' ==> success (f 🍋 g) h" by (auto simp add: effect_def success_def bind_def)
lemma effect_bindI [effect_intros]: assumes"effect f h h' r""effect (g r) h' h'' r'" shows"effect (f 🍋 g) h h'' r'" using assms apply (auto intro!: effectI elim!: effectE successE) apply (subst execute_bind, simp_all) done
lemma effect_bindE [effect_elims]: assumes"effect (f 🍋 g) h h'' r'" obtains h' r where"effect f h h' r""effect (g r) h' h'' r'" using assms by (auto simp add: effect_def bind_def split: option.split_asm)
lemma execute_bind_eq_SomeI: assumes"execute f h = Some (x, h')" and"execute (g x) h' = Some (y, h'')" shows"execute (f 🍋 g) h = Some (y, h'')" using assms by (simp add: bind_def)
lemma return_bind [simp]: "return x 🍋 f = f x" by (rule Heap_eqI) (simp add: execute_simps)
lemma bind_bind [simp]: "(f 🍋 g) 🍋 k = (f :: 'a Heap) 🍋 (λx. g x 🍋 k)" by (rule Heap_eqI) (simp add: bind_def execute_simps split: option.splits)
lemma raise_bind [simp]: "raise e 🍋 f = raise e" by (rule Heap_eqI) (simp add: execute_simps)
subsection‹Generic combinators›
subsubsection ‹Assertions›
definition assert :: "('a ==> bool) ==> 'a ==> 'a Heap"where "assert P x = (if P x then return x else raise STR ''assert'')"
lemma execute_assert [execute_simps]: "P x ==> execute (assert P x) h = Some (x, h)" "¬ P x ==> execute (assert P x) h = None" by (simp_all add: assert_def execute_simps)
lemma success_assertI [success_intros]: "P x ==> success (assert P x) h" by (rule successI) (simp add: execute_assert)
lemma effect_assertI [effect_intros]: "P x ==> h' = h ==> r = x ==> effect (assert P x) h h' r" by (rule effectI) (simp add: execute_assert)
lemma effect_assertE [effect_elims]: assumes"effect (assert P x) h h' r" obtains"P x""r = x""h' = h" using assms by (rule effectE) (cases "P x", simp_all add: execute_assert success_def)
lemma assert_cong [fundef_cong]: assumes"P = P'" assumes"∧x. P' x ==> f x = f' x" shows"(assert P x 🍋 f) = (assert P' x 🍋 f')" by (rule Heap_eqI) (insert assms, simp add: assert_def)
subsubsection ‹Plain lifting›
definition lift :: "('a ==> 'b) ==> 'a ==> 'b Heap"where "lift f = return o f"
lemma lift_collapse [simp]: "lift f x = return (f x)" by (simp add: lift_def)
subsubsection ‹Iteration -- warning: this is rarely useful!›
primrec fold_map :: "('a ==> 'b Heap) ==> 'a list ==> 'b list Heap"where "fold_map f [] = return []"
| "fold_map f (x # xs) = do { y ← f x; ys ← fold_map f xs; return (y # ys) }"
lemma fold_map_append: "fold_map f (xs @ ys) = fold_map f xs 🍋 (λxs. fold_map f ys 🍋 (λys. return (xs @ ys)))" by (induct xs) simp_all
lemma execute_fold_map_unchanged_heap [execute_simps]: assumes"∧x. x ∈ set xs ==>∃y. execute (f x) h = Some (y, h)" shows"execute (fold_map f xs) h = Some (List.map (λx. fst (the (execute (f x) h))) xs, h)" using assms proof (induct xs) case Nil show ?caseby (simp add: execute_simps) next case (Cons x xs) from Cons.prems obtain y where y: "execute (f x) h = Some (y, h)"by auto moreoverfrom Cons.prems Cons.hyps have"execute (fold_map f xs) h = Some (map (λx. fst (the (execute (f x) h))) xs, h)"by auto ultimatelyshow ?caseby (simp, simp only: execute_bind(1), simp add: execute_simps) qed
lemma heap_step_admissible: "option.admissible (λf:: 'a => ('b * 'c) option. ∀h h' r. f h = Some (r, h') ⟶ P x h h' r)" proof (rule ccpo.admissibleI) fix A :: "('a ==> ('b * 'c) option) set" assume ch: "Complete_Partial_Order.chain option.le_fun A" and IH: "∀f∈A. ∀h h' r. f h = Some (r, h') ⟶ P x h h' r" from ch have ch': "∧x. Complete_Partial_Order.chain option_ord {y. ∃f∈A. y = f x}"by(rule chain_fun) show"∀h h' r. option.lub_fun A h = Some (r, h') ⟶ P x h h' r" proof (intro allI impI) fix h h' r assume"option.lub_fun A h = Some (r, h')" from flat_lub_in_chain[OF ch' this[unfolded fun_lub_def]] have"Some (r, h') ∈ {y. ∃f∈A. y = f h}"by simp thenhave"∃f∈A. f h = Some (r, h')"by auto with IH show"P x h h' r"by auto qed qed
lemma admissible_heap: "heap.admissible (λf. ∀x h h' r. effect (f x) h h' r ⟶ P x h h' r)" proof (rule admissible_fun[OF heap_interpretation]) fix x show"ccpo.admissible Heap_lub Heap_ord (λa. ∀h h' r. effect a h h' r ⟶ P x h h' r)" unfolding Heap_ord_def Heap_lub_def proof (intro admissible_image partial_function_lift flat_interpretation) show"option.admissible ((λa. ∀h h' r. effect a h h' r ⟶ P x h h' r) ∘ Heap)" unfolding comp_def effect_def execute.simps by (rule heap_step_admissible) qed (auto simp add: Heap_eqI) qed
lemma fixp_induct_heap: fixes F :: "'c ==> 'c"and
U :: "'c ==> 'b ==> 'a Heap"and
C :: "('b ==> 'a Heap) ==> 'c"and
P :: "'b ==> heap ==> heap ==> 'a ==> bool" assumes mono: "∧x. monotone (fun_ord Heap_ord) Heap_ord (λf. U (F (C f)) x)" assumes eq: "f ≡ C (ccpo.fixp (fun_lub Heap_lub) (fun_ord Heap_ord) (λf. U (F (C f))))" assumes inverse2: "∧f. U (C f) = f" assumes step: "∧f x h h' r. (∧x h h' r. effect (U f x) h h' r ==> P x h h' r) ==> effect (U (F f) x) h h' r ==> P x h h' r" assumes defined: "effect (U f x) h h' r" shows"P x h h' r" using step defined heap.fixp_induct_uc[of U F C, OF mono eq inverse2 admissible_heap, of P] unfolding effect_def execute.simps by blast
lemma Heap_ordI: assumes"∧h. execute x h = None ∨ execute x h = execute y h" shows"Heap_ord x y" using assms unfolding Heap_ord_def img_ord_def fun_ord_def flat_ord_def by blast
lemma Heap_ordE: assumes"Heap_ord x y" obtains"execute x h = None" | "execute x h = execute y h" using assms unfolding Heap_ord_def img_ord_def fun_ord_def flat_ord_def by atomize_elim blast
lemma bind_mono [partial_function_mono]: assumes mf: "mono_Heap B"and mg: "∧y. mono_Heap (λf. C y f)" shows"mono_Heap (λf. B f 🍋 (λy. C y f))" proof (rule monotoneI) fix f g :: "'a ==> 'b Heap"assume fg: "fun_ord Heap_ord f g" from mf have 1: "Heap_ord (B f) (B g)"by (rule monotoneD) (rule fg) from mg have 2: "∧y'. Heap_ord (C y' f) (C y' g)"by (rule monotoneD) (rule fg)
have"Heap_ord (B f 🍋 (λy. C y f)) (B g 🍋 (λy. C y f))"
(is"Heap_ord ?L ?R") proof (rule Heap_ordI) fix h from 1 show"execute ?L h = None ∨ execute ?L h = execute ?R h" by (rule Heap_ordE[where h = h]) (auto simp: execute_bind_case) qed also have"Heap_ord (B g 🍋 (λy'. C y' f)) (B g 🍋 (λy'. C y' g))"
(is"Heap_ord ?L ?R") proof (rule Heap_ordI) fix h show"execute ?L h = None ∨ execute ?L h = execute ?R h" proof (cases "execute (B g) h") case None thenhave"execute ?L h = None"by (auto simp: execute_bind_case) thus ?thesis .. next case Some thenobtain r h' where"execute (B g) h = Some (r, h')" by (metis surjective_pairing) thenhave"execute ?L h = execute (C r f) h'" "execute ?R h = execute (C r g) h'" by (auto simp: execute_bind_case) with 2[of r] show ?thesis by (auto elim: Heap_ordE) qed qed finally (heap.leq_trans) show"Heap_ord (B f 🍋 (λy. C y f)) (B g 🍋 (λy'. C y' g))" . qed
code_printing code_module"Heap"⇀ (Haskell) ‹ module Heap(ST, RealWorld, STRef, newSTRef, readSTRef, writeSTRef, STArray, newArray, newListArray, newFunArray, lengthArray, readArray, writeArray) where import Control.Monad(liftM) import Control.Monad.ST(RealWorld, ST) import Data.STRef(STRef, newSTRef, readSTRef, writeSTRef) import qualified Data.Array.ST type STArray s a = Data.Array.ST.STArray s Integer a newArray :: Integer -> a -> ST s (STArray s a) newArray k = Data.Array.ST.newArray (0, k - 1) newListArray :: [a] -> ST s (STArray s a) newListArray xs = Data.Array.ST.newListArray (0, (fromInteger . toInteger . length) xs - 1) xs newFunArray :: Integer -> (Integer -> a) -> ST s (STArray s a) newFunArray k f = Data.Array.ST.newListArray (0, k - 1) (map f [0..k-1]) lengthArray :: STArray s a -> ST s Integer lengthArray a = liftM (\(_, l) -> l + 1) (Data.Array.ST.getBounds a) readArray :: STArray s a -> Integer -> ST s a readArray = Data.Array.ST.readArray writeArray :: STArray s a -> Integer -> a -> ST s () writeArray = Data.Array.ST.writeArray›
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.