diff -r 59caa6180fff -r bf86a65403a8 src/HOL/Imperative_HOL/Heap_Monad.thy --- a/src/HOL/Imperative_HOL/Heap_Monad.thy Fri Jul 09 10:08:10 2010 +0200 +++ b/src/HOL/Imperative_HOL/Heap_Monad.thy Fri Jul 09 16:58:44 2010 +0200 @@ -10,7 +10,7 @@ subsection {* The monad *} -subsubsection {* Monad combinators *} +subsubsection {* Monad construction *} text {* Monadic heap actions either produce values and transform the heap, or fail *} @@ -19,6 +19,13 @@ primrec execute :: "'a Heap \ heap \ ('a \ heap) option" where [code del]: "execute (Heap f) = f" +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_execute [simp]: "Heap (execute f) = f" by (cases f) simp_all @@ -26,43 +33,98 @@ "(\h. execute f h = execute g h) \ f = g" by (cases f, cases g) (auto simp: expand_fun_eq) -lemma Heap_eqI': - "(\h. (\x. execute (f x) h) = (\y. execute (g y) h)) \ f = g" - by (auto simp: expand_fun_eq intro: Heap_eqI) +ML {* structure Execute_Simps = Named_Thms( + val name = "execute_simps" + val description = "simplification rules for execute" +) *} + +setup Execute_Simps.setup + +lemma execute_Let [simp, 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 [simp, 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 [simp]: +lemma execute_heap [simp, 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 [simp]: +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 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 + +subsubsection {* Predicate classifying successful computations *} + +definition success :: "'a Heap \ heap \ bool" where + "success f h \ execute f h \ None" + +lemma successI: + "execute f h \ None \ success f h" + by (simp add: success_def) + +lemma successE: + assumes "success f h" + obtains r h' where "execute f h = Some (r, h')" + using assms by (auto simp add: success_def) + +ML {* structure Success_Intros = Named_Thms( + val name = "success_intros" + val description = "introduction rules for success" +) *} + +setup Success_Intros.setup + +lemma success_tapI [iff, success_intros]: + "success (tap f) h" + by (rule successI) simp + +lemma success_heapI [iff, success_intros]: + "success (heap f) h" + by (rule successI) simp + +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) + + +subsubsection {* Monad combinators *} definition return :: "'a \ 'a Heap" where [code del]: "return x = heap (Pair x)" -lemma execute_return [simp]: +lemma execute_return [simp, execute_simps]: "execute (return x) = Some \ Pair x" by (simp add: return_def) +lemma success_returnI [iff, success_intros]: + "success (return x) h" + by (rule successI) simp + definition raise :: "string \ 'a Heap" where -- {* the string is just decoration *} [code del]: "raise s = Heap (\_. None)" -lemma execute_raise [simp]: +lemma execute_raise [simp, execute_simps]: "execute (raise s) = (\_. None)" by (simp add: raise_def) @@ -73,14 +135,18 @@ notation bind (infixl "\=" 54) -lemma execute_bind [simp]: +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_heap [simp]: - "execute (heap f \= g) h = execute (g (fst (f h))) (snd (f h))" - by (simp add: bind_def split_def) +lemma success_bindI [success_intros]: + "success f h \ success (g (fst (the (execute f h)))) (snd (the (execute f h))) \ success (f \= g) h" + by (auto intro!: successI elim!: successE simp add: bind_def) + +lemma execute_bind_successI [execute_simps]: + "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 execute_eq_SomeI: assumes "Heap_Monad.execute f h = Some (x, h')" @@ -89,7 +155,7 @@ using assms by (simp add: bind_def) lemma return_bind [simp]: "return x \= f = f x" - by (rule Heap_eqI) simp + by (rule Heap_eqI) (simp add: execute_bind) lemma bind_return [simp]: "f \= return = f" by (rule Heap_eqI) (simp add: bind_def split: option.splits) @@ -98,7 +164,7 @@ by (rule Heap_eqI) (simp add: bind_def split: option.splits) lemma raise_bind [simp]: "raise e \= f = raise e" - by (rule Heap_eqI) simp + by (rule Heap_eqI) (simp add: execute_bind) abbreviation chain :: "'a Heap \ 'b Heap \ 'b Heap" (infixl ">>" 54) where "f >> g \ f >>= (\_. g)" @@ -187,24 +253,31 @@ *} -subsection {* Monad properties *} +subsection {* Generic combinators *} -subsection {* Generic combinators *} +subsubsection {* Assertions *} definition assert :: "('a \ bool) \ 'a \ 'a Heap" where "assert P x = (if P x then return x else raise ''assert'')" -lemma execute_assert [simp]: +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) +lemma success_assertI [success_intros]: + "P x \ success (assert P x) h" + by (rule successI) (simp add: execute_assert) + 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" @@ -216,6 +289,9 @@ "(f \= lift g) = (f \= (\x. return (g x)))" by (simp add: lift_def comp_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 @@ -228,7 +304,7 @@ "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: +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)" @@ -527,6 +603,6 @@ code_const return (Haskell "return") code_const Heap_Monad.raise' (Haskell "error/ _") -hide_const (open) Heap heap guard execute raise' fold_map +hide_const (open) Heap heap guard raise' fold_map end