| author | wenzelm | 
| Tue, 30 Mar 2010 00:12:42 +0200 | |
| changeset 36014 | c51a077680e4 | 
| parent 35719 | 99b6152aedf5 | 
| child 36176 | 3fe7e97ccca8 | 
| permissions | -rw-r--r-- | 
| 30246 | 1 | (* Title: HOL/Option.thy | 
| 2 | Author: Folklore | |
| 3 | *) | |
| 4 | ||
| 5 | header {* Datatype option *}
 | |
| 6 | ||
| 7 | theory Option | |
| 35719 
99b6152aedf5
split off theory Big_Operators from theory Finite_Set
 haftmann parents: 
34886diff
changeset | 8 | imports Datatype | 
| 30246 | 9 | begin | 
| 10 | ||
| 11 | datatype 'a option = None | Some 'a | |
| 12 | ||
| 13 | lemma not_None_eq [iff]: "(x ~= None) = (EX y. x = Some y)" | |
| 14 | by (induct x) auto | |
| 15 | ||
| 16 | lemma not_Some_eq [iff]: "(ALL y. x ~= Some y) = (x = None)" | |
| 17 | by (induct x) auto | |
| 18 | ||
| 19 | text{*Although it may appear that both of these equalities are helpful
 | |
| 20 | only when applied to assumptions, in practice it seems better to give | |
| 21 | them the uniform iff attribute. *} | |
| 22 | ||
| 31080 | 23 | lemma inj_Some [simp]: "inj_on Some A" | 
| 24 | by (rule inj_onI) simp | |
| 25 | ||
| 30246 | 26 | lemma option_caseE: | 
| 27 | assumes c: "(case x of None => P | Some y => Q y)" | |
| 28 | obtains | |
| 29 | (None) "x = None" and P | |
| 30 | | (Some) y where "x = Some y" and "Q y" | |
| 31 | using c by (cases x) simp_all | |
| 32 | ||
| 31080 | 33 | lemma UNIV_option_conv: "UNIV = insert None (range Some)" | 
| 34 | by(auto intro: classical) | |
| 35 | ||
| 30246 | 36 | |
| 37 | subsubsection {* Operations *}
 | |
| 38 | ||
| 39 | primrec the :: "'a option => 'a" where | |
| 40 | "the (Some x) = x" | |
| 41 | ||
| 42 | primrec set :: "'a option => 'a set" where | |
| 43 | "set None = {}" |
 | |
| 44 | "set (Some x) = {x}"
 | |
| 45 | ||
| 46 | lemma ospec [dest]: "(ALL x:set A. P x) ==> A = Some x ==> P x" | |
| 47 | by simp | |
| 48 | ||
| 49 | declaration {* fn _ =>
 | |
| 50 |   Classical.map_cs (fn cs => cs addSD2 ("ospec", thm "ospec"))
 | |
| 51 | *} | |
| 52 | ||
| 53 | lemma elem_set [iff]: "(x : set xo) = (xo = Some x)" | |
| 54 | by (cases xo) auto | |
| 55 | ||
| 56 | lemma set_empty_eq [simp]: "(set xo = {}) = (xo = None)"
 | |
| 57 | by (cases xo) auto | |
| 58 | ||
| 31154 | 59 | definition map :: "('a \<Rightarrow> 'b) \<Rightarrow> 'a option \<Rightarrow> 'b option" where
 | 
| 60 | "map = (%f y. case y of None => None | Some x => Some (f x))" | |
| 30246 | 61 | |
| 62 | lemma option_map_None [simp, code]: "map f None = None" | |
| 63 | by (simp add: map_def) | |
| 64 | ||
| 65 | lemma option_map_Some [simp, code]: "map f (Some x) = Some (f x)" | |
| 66 | by (simp add: map_def) | |
| 67 | ||
| 68 | lemma option_map_is_None [iff]: | |
| 69 | "(map f opt = None) = (opt = None)" | |
| 70 | by (simp add: map_def split add: option.split) | |
| 71 | ||
| 72 | lemma option_map_eq_Some [iff]: | |
| 73 | "(map f xo = Some y) = (EX z. xo = Some z & f z = y)" | |
| 74 | by (simp add: map_def split add: option.split) | |
| 75 | ||
| 76 | lemma option_map_comp: | |
| 77 | "map f (map g opt) = map (f o g) opt" | |
| 78 | by (simp add: map_def split add: option.split) | |
| 79 | ||
| 80 | lemma option_map_o_sum_case [simp]: | |
| 81 | "map f o sum_case g h = sum_case (map f o g) (map f o h)" | |
| 82 | by (rule ext) (simp split: sum.split) | |
| 83 | ||
| 84 | ||
| 85 | hide (open) const set map | |
| 86 | ||
| 87 | subsubsection {* Code generator setup *}
 | |
| 88 | ||
| 31154 | 89 | definition is_none :: "'a option \<Rightarrow> bool" where | 
| 31998 
2c7a24f74db9
code attributes use common underscore convention
 haftmann parents: 
31154diff
changeset | 90 | [code_post]: "is_none x \<longleftrightarrow> x = None" | 
| 30246 | 91 | |
| 92 | lemma is_none_code [code]: | |
| 93 | shows "is_none None \<longleftrightarrow> True" | |
| 94 | and "is_none (Some x) \<longleftrightarrow> False" | |
| 31154 | 95 | unfolding is_none_def by simp_all | 
| 96 | ||
| 97 | lemma is_none_none: | |
| 98 | "is_none x \<longleftrightarrow> x = None" | |
| 99 | by (simp add: is_none_def) | |
| 100 | ||
| 32069 
6d28bbd33e2c
prefer code_inline over code_unfold; use code_unfold_post where appropriate
 haftmann parents: 
31998diff
changeset | 101 | lemma [code_unfold]: | 
| 31154 | 102 | "eq_class.eq x None \<longleftrightarrow> is_none x" | 
| 103 | by (simp add: eq is_none_none) | |
| 30246 | 104 | |
| 105 | hide (open) const is_none | |
| 106 | ||
| 107 | code_type option | |
| 108 | (SML "_ option") | |
| 109 | (OCaml "_ option") | |
| 110 | (Haskell "Maybe _") | |
| 34886 | 111 | (Scala "!Option[(_)]") | 
| 30246 | 112 | |
| 113 | code_const None and Some | |
| 114 | (SML "NONE" and "SOME") | |
| 115 | (OCaml "None" and "Some _") | |
| 116 | (Haskell "Nothing" and "Just") | |
| 34886 | 117 | (Scala "None" and "!Some((_))") | 
| 30246 | 118 | |
| 119 | code_instance option :: eq | |
| 120 | (Haskell -) | |
| 121 | ||
| 122 | code_const "eq_class.eq \<Colon> 'a\<Colon>eq option \<Rightarrow> 'a option \<Rightarrow> bool" | |
| 123 | (Haskell infixl 4 "==") | |
| 124 | ||
| 125 | code_reserved SML | |
| 126 | option NONE SOME | |
| 127 | ||
| 128 | code_reserved OCaml | |
| 129 | option None Some | |
| 130 | ||
| 34886 | 131 | code_reserved Scala | 
| 132 | Option None Some | |
| 133 | ||
| 30246 | 134 | end |