(* Title: HOL/HOLCF/Library/Option_Cpo.thy Author: Brian Huffman
*)
section \<open>Cpo class instance for HOL option type\<close>
theory Option_Cpo imports HOLCF Sum_Cpo begin
subsection \<open>Ordering on option type\<close>
instantiation option :: (below) below begin
definition below_option_def: "x \ y \ case x of
None \<Rightarrow> (case y of None \<Rightarrow> True | Some b \<Rightarrow> False) |
Some a \<Rightarrow> (case y of None \<Rightarrow> False | Some b \<Rightarrow> a \<sqsubseteq> b)"
instance .. end
lemma None_below_None [simp]: "None \ None" unfolding below_option_def by simp
lemma Some_below_Some [simp]: "Some x \ Some y \ x \ y" unfolding below_option_def by simp
lemma Some_below_None [simp]: "\ Some x \ None" unfolding below_option_def by simp
lemma None_below_Some [simp]: "\ None \ Some y" unfolding below_option_def by simp
lemma Some_mono: "x \ y \ Some x \ Some y" by simp
lemma None_below_iff [simp]: "None \ x \ x = None" by (cases x, simp_all)
lemma below_None_iff [simp]: "x \ None \ x = None" by (cases x, simp_all)
lemma option_below_cases: assumes"x \ y" obtains"x = None"and"y = None"
| a b where"x = Some a"and"y = Some b"and"a \ b" using assms unfolding below_option_def by (simp split: option.split_asm)
subsection \<open>Option type is a complete partial order\<close>
instance option :: (po) po proof fix x :: "'a option" show"x \ x" unfolding below_option_def by (simp split: option.split) next fix x y :: "'a option" assume"x \ y" and "y \ x" thus "x = y" unfolding below_option_def by (auto split: option.split_asm intro: below_antisym) next fix x y z :: "'a option" assume"x \ y" and "y \ z" thus "x \ z" unfolding below_option_def by (auto split: option.split_asm intro: below_trans) qed
lemma monofun_the: "monofun the" by (rule monofunI, erule option_below_cases, simp_all)
lemma option_chain_cases: assumes Y: "chain Y" obtains"Y = (\i. None)" | A where "chain A" and "Y = (\i. Some (A i))" apply (cases "Y 0") apply (rule that(1)) apply (rule ext) apply (cut_tac j=i in chain_mono [OF Y le0], simp) apply (rule that(2)) apply (rule ch2ch_monofun [OF monofun_the Y]) apply (rule ext) apply (cut_tac j=i in chain_mono [OF Y le0], simp) apply (case_tac "Y i", simp_all) done
lemma is_lub_Some: "range S <<| x \ range (\i. Some (S i)) <<| Some x" apply (rule is_lubI) apply (rule ub_rangeI) apply (simp add: is_lub_rangeD1) apply (frule ub_rangeD [where i=arbitrary]) apply (case_tac u, simp_all) apply (erule is_lubD2) apply (rule ub_rangeI) apply (drule ub_rangeD, simp) done
lemma cont2cont_case_option: assumes f: "cont (\x. f x)" assumes g: "cont (\x. g x)" assumes h1: "\a. cont (\x. h x a)" assumes h2: "\x. cont (\a. h x a)" shows"cont (\x. case f x of None \ g x | Some a \ h x a)" apply (rule cont_apply [OF f]) apply (rule contI) apply (erule option_chain_cases) apply (simp add: is_lub_const) apply (simp add: lub_Some) apply (simp add: cont2contlubE [OF h2]) apply (rule cpo_lubI, rule chainI) apply (erule cont2monofunE [OF h2 chainE]) apply (case_tac y, simp_all add: g h1) done
lemma cont2cont_case_option' [simp, cont2cont]: assumes f: "cont (\x. f x)" assumes g: "cont (\x. g x)" assumes h: "cont (\p. h (fst p) (snd p))" shows"cont (\x. case f x of None \ g x | Some a \ h x a)" using assms by (simp add: cont2cont_case_option prod_cont_iff)
text\<open>Simple version for when the element type is not a cpo.\<close>
lemma cont2cont_case_option_simple [simp, cont2cont]: assumes"cont (\x. f x)" assumes"\a. cont (\x. g x a)" shows"cont (\x. case z of None \ f x | Some a \ g x a)" using assms by (cases z) auto
text\<open>Continuity rule for map.\<close>
lemma cont2cont_map_option [simp, cont2cont]: assumes f: "cont (\(x, y). f x y)" assumes g: "cont (\x. g x)" shows"cont (\x. map_option (\y. f x y) (g x))" using assms by (simp add: prod_cont_iff map_option_case)
subsection \<open>Compactness and chain-finiteness\<close>