18 "tl [] = []" |
18 "tl [] = []" |
19 |
19 |
20 datatype_compat list |
20 datatype_compat list |
21 |
21 |
22 lemma [case_names Nil Cons, cases type: list]: |
22 lemma [case_names Nil Cons, cases type: list]: |
23 -- \<open>for backward compatibility -- names of variables differ\<close> |
23 \<comment> \<open>for backward compatibility -- names of variables differ\<close> |
24 "(y = [] \<Longrightarrow> P) \<Longrightarrow> (\<And>a list. y = a # list \<Longrightarrow> P) \<Longrightarrow> P" |
24 "(y = [] \<Longrightarrow> P) \<Longrightarrow> (\<And>a list. y = a # list \<Longrightarrow> P) \<Longrightarrow> P" |
25 by (rule list.exhaust) |
25 by (rule list.exhaust) |
26 |
26 |
27 lemma [case_names Nil Cons, induct type: list]: |
27 lemma [case_names Nil Cons, induct type: list]: |
28 -- \<open>for backward compatibility -- names of variables differ\<close> |
28 \<comment> \<open>for backward compatibility -- names of variables differ\<close> |
29 "P [] \<Longrightarrow> (\<And>a list. P list \<Longrightarrow> P (a # list)) \<Longrightarrow> P list" |
29 "P [] \<Longrightarrow> (\<And>a list. P list \<Longrightarrow> P (a # list)) \<Longrightarrow> P list" |
30 by (rule list.induct) |
30 by (rule list.induct) |
31 |
31 |
32 text \<open>Compatibility:\<close> |
32 text \<open>Compatibility:\<close> |
33 |
33 |
76 primrec filter:: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
76 primrec filter:: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
77 "filter P [] = []" | |
77 "filter P [] = []" | |
78 "filter P (x # xs) = (if P x then x # filter P xs else filter P xs)" |
78 "filter P (x # xs) = (if P x then x # filter P xs else filter P xs)" |
79 |
79 |
80 syntax |
80 syntax |
81 -- \<open>Special syntax for filter\<close> |
81 \<comment> \<open>Special syntax for filter\<close> |
82 "_filter" :: "[pttrn, 'a list, bool] => 'a list" ("(1[_<-_./ _])") |
82 "_filter" :: "[pttrn, 'a list, bool] => 'a list" ("(1[_<-_./ _])") |
83 syntax (xsymbols) |
83 syntax (xsymbols) |
84 "_filter" :: "[pttrn, 'a list, bool] => 'a list"("(1[_\<leftarrow>_ ./ _])") |
84 "_filter" :: "[pttrn, 'a list, bool] => 'a list"("(1[_\<leftarrow>_ ./ _])") |
85 translations |
85 translations |
86 "[x<-xs . P]"== "CONST filter (%x. P) xs" |
86 "[x<-xs . P]"== "CONST filter (%x. P) xs" |
102 "concat (x # xs) = x @ concat xs" |
102 "concat (x # xs) = x @ concat xs" |
103 |
103 |
104 primrec drop:: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
104 primrec drop:: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
105 drop_Nil: "drop n [] = []" | |
105 drop_Nil: "drop n [] = []" | |
106 drop_Cons: "drop n (x # xs) = (case n of 0 \<Rightarrow> x # xs | Suc m \<Rightarrow> drop m xs)" |
106 drop_Cons: "drop n (x # xs) = (case n of 0 \<Rightarrow> x # xs | Suc m \<Rightarrow> drop m xs)" |
107 -- \<open>Warning: simpset does not contain this definition, but separate |
107 \<comment> \<open>Warning: simpset does not contain this definition, but separate |
108 theorems for @{text "n = 0"} and @{text "n = Suc k"}\<close> |
108 theorems for \<open>n = 0\<close> and \<open>n = Suc k\<close>\<close> |
109 |
109 |
110 primrec take:: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
110 primrec take:: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
111 take_Nil:"take n [] = []" | |
111 take_Nil:"take n [] = []" | |
112 take_Cons: "take n (x # xs) = (case n of 0 \<Rightarrow> [] | Suc m \<Rightarrow> x # take m xs)" |
112 take_Cons: "take n (x # xs) = (case n of 0 \<Rightarrow> [] | Suc m \<Rightarrow> x # take m xs)" |
113 -- \<open>Warning: simpset does not contain this definition, but separate |
113 \<comment> \<open>Warning: simpset does not contain this definition, but separate |
114 theorems for @{text "n = 0"} and @{text "n = Suc k"}\<close> |
114 theorems for \<open>n = 0\<close> and \<open>n = Suc k\<close>\<close> |
115 |
115 |
116 primrec (nonexhaustive) nth :: "'a list => nat => 'a" (infixl "!" 100) where |
116 primrec (nonexhaustive) nth :: "'a list => nat => 'a" (infixl "!" 100) where |
117 nth_Cons: "(x # xs) ! n = (case n of 0 \<Rightarrow> x | Suc k \<Rightarrow> xs ! k)" |
117 nth_Cons: "(x # xs) ! n = (case n of 0 \<Rightarrow> x | Suc k \<Rightarrow> xs ! k)" |
118 -- \<open>Warning: simpset does not contain this definition, but separate |
118 \<comment> \<open>Warning: simpset does not contain this definition, but separate |
119 theorems for @{text "n = 0"} and @{text "n = Suc k"}\<close> |
119 theorems for \<open>n = 0\<close> and \<open>n = Suc k\<close>\<close> |
120 |
120 |
121 primrec list_update :: "'a list \<Rightarrow> nat \<Rightarrow> 'a \<Rightarrow> 'a list" where |
121 primrec list_update :: "'a list \<Rightarrow> nat \<Rightarrow> 'a \<Rightarrow> 'a list" where |
122 "list_update [] i v = []" | |
122 "list_update [] i v = []" | |
123 "list_update (x # xs) i v = |
123 "list_update (x # xs) i v = |
124 (case i of 0 \<Rightarrow> v # xs | Suc j \<Rightarrow> x # list_update xs j v)" |
124 (case i of 0 \<Rightarrow> v # xs | Suc j \<Rightarrow> x # list_update xs j v)" |
145 |
145 |
146 primrec zip :: "'a list \<Rightarrow> 'b list \<Rightarrow> ('a \<times> 'b) list" where |
146 primrec zip :: "'a list \<Rightarrow> 'b list \<Rightarrow> ('a \<times> 'b) list" where |
147 "zip xs [] = []" | |
147 "zip xs [] = []" | |
148 zip_Cons: "zip xs (y # ys) = |
148 zip_Cons: "zip xs (y # ys) = |
149 (case xs of [] => [] | z # zs => (z, y) # zip zs ys)" |
149 (case xs of [] => [] | z # zs => (z, y) # zip zs ys)" |
150 -- \<open>Warning: simpset does not contain this definition, but separate |
150 \<comment> \<open>Warning: simpset does not contain this definition, but separate |
151 theorems for @{text "xs = []"} and @{text "xs = z # zs"}\<close> |
151 theorems for \<open>xs = []\<close> and \<open>xs = z # zs\<close>\<close> |
152 |
152 |
153 primrec product :: "'a list \<Rightarrow> 'b list \<Rightarrow> ('a \<times> 'b) list" where |
153 primrec product :: "'a list \<Rightarrow> 'b list \<Rightarrow> ('a \<times> 'b) list" where |
154 "product [] _ = []" | |
154 "product [] _ = []" | |
155 "product (x#xs) ys = map (Pair x) ys @ product xs ys" |
155 "product (x#xs) ys = map (Pair x) ys @ product xs ys" |
156 |
156 |
175 |
175 |
176 primrec find :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a option" where |
176 primrec find :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a option" where |
177 "find _ [] = None" | |
177 "find _ [] = None" | |
178 "find P (x#xs) = (if P x then Some x else find P xs)" |
178 "find P (x#xs) = (if P x then Some x else find P xs)" |
179 |
179 |
180 text \<open>In the context of multisets, @{text count_list} is equivalent to |
180 text \<open>In the context of multisets, \<open>count_list\<close> is equivalent to |
181 @{term "count o mset"} and it it advisable to use the latter.\<close> |
181 @{term "count o mset"} and it it advisable to use the latter.\<close> |
182 primrec count_list :: "'a list \<Rightarrow> 'a \<Rightarrow> nat" where |
182 primrec count_list :: "'a list \<Rightarrow> 'a \<Rightarrow> nat" where |
183 "count_list [] y = 0" | |
183 "count_list [] y = 0" | |
184 "count_list (x#xs) y = (if x=y then count_list xs y + 1 else count_list xs y)" |
184 "count_list (x#xs) y = (if x=y then count_list xs y + 1 else count_list xs y)" |
185 |
185 |
223 primrec replicate :: "nat \<Rightarrow> 'a \<Rightarrow> 'a list" where |
223 primrec replicate :: "nat \<Rightarrow> 'a \<Rightarrow> 'a list" where |
224 replicate_0: "replicate 0 x = []" | |
224 replicate_0: "replicate 0 x = []" | |
225 replicate_Suc: "replicate (Suc n) x = x # replicate n x" |
225 replicate_Suc: "replicate (Suc n) x = x # replicate n x" |
226 |
226 |
227 text \<open> |
227 text \<open> |
228 Function @{text size} is overloaded for all datatypes. Users may |
228 Function \<open>size\<close> is overloaded for all datatypes. Users may |
229 refer to the list version as @{text length}.\<close> |
229 refer to the list version as \<open>length\<close>.\<close> |
230 |
230 |
231 abbreviation length :: "'a list \<Rightarrow> nat" where |
231 abbreviation length :: "'a list \<Rightarrow> nat" where |
232 "length \<equiv> size" |
232 "length \<equiv> size" |
233 |
233 |
234 definition enumerate :: "nat \<Rightarrow> 'a list \<Rightarrow> (nat \<times> 'a) list" where |
234 definition enumerate :: "nat \<Rightarrow> 'a list \<Rightarrow> (nat \<times> 'a) list" where |
365 |
365 |
366 |
366 |
367 subsubsection \<open>List comprehension\<close> |
367 subsubsection \<open>List comprehension\<close> |
368 |
368 |
369 text\<open>Input syntax for Haskell-like list comprehension notation. |
369 text\<open>Input syntax for Haskell-like list comprehension notation. |
370 Typical example: @{text"[(x,y). x \<leftarrow> xs, y \<leftarrow> ys, x \<noteq> y]"}, |
370 Typical example: \<open>[(x,y). x \<leftarrow> xs, y \<leftarrow> ys, x \<noteq> y]\<close>, |
371 the list of all pairs of distinct elements from @{text xs} and @{text ys}. |
371 the list of all pairs of distinct elements from \<open>xs\<close> and \<open>ys\<close>. |
372 The syntax is as in Haskell, except that @{text"|"} becomes a dot |
372 The syntax is as in Haskell, except that \<open>|\<close> becomes a dot |
373 (like in Isabelle's set comprehension): @{text"[e. x \<leftarrow> xs, \<dots>]"} rather than |
373 (like in Isabelle's set comprehension): \<open>[e. x \<leftarrow> xs, \<dots>]\<close> rather than |
374 \verb![e| x <- xs, ...]!. |
374 \verb![e| x <- xs, ...]!. |
375 |
375 |
376 The qualifiers after the dot are |
376 The qualifiers after the dot are |
377 \begin{description} |
377 \begin{description} |
378 \item[generators] @{text"p \<leftarrow> xs"}, |
378 \item[generators] \<open>p \<leftarrow> xs\<close>, |
379 where @{text p} is a pattern and @{text xs} an expression of list type, or |
379 where \<open>p\<close> is a pattern and \<open>xs\<close> an expression of list type, or |
380 \item[guards] @{text"b"}, where @{text b} is a boolean expression. |
380 \item[guards] \<open>b\<close>, where \<open>b\<close> is a boolean expression. |
381 %\item[local bindings] @ {text"let x = e"}. |
381 %\item[local bindings] @ {text"let x = e"}. |
382 \end{description} |
382 \end{description} |
383 |
383 |
384 Just like in Haskell, list comprehension is just a shorthand. To avoid |
384 Just like in Haskell, list comprehension is just a shorthand. To avoid |
385 misunderstandings, the translation into desugared form is not reversed |
385 misunderstandings, the translation into desugared form is not reversed |
386 upon output. Note that the translation of @{text"[e. x \<leftarrow> xs]"} is |
386 upon output. Note that the translation of \<open>[e. x \<leftarrow> xs]\<close> is |
387 optmized to @{term"map (%x. e) xs"}. |
387 optmized to @{term"map (%x. e) xs"}. |
388 |
388 |
389 It is easy to write short list comprehensions which stand for complex |
389 It is easy to write short list comprehensions which stand for complex |
390 expressions. During proofs, they may become unreadable (and |
390 expressions. During proofs, they may become unreadable (and |
391 mangled). In such cases it can be advisable to introduce separate |
391 mangled). In such cases it can be advisable to introduce separate |
2932 by (induct xs) simp_all |
2931 by (induct xs) simp_all |
2933 |
2932 |
2934 lemma foldl_conv_fold: "foldl f s xs = fold (\<lambda>x s. f s x) xs s" |
2933 lemma foldl_conv_fold: "foldl f s xs = fold (\<lambda>x s. f s x) xs s" |
2935 by (induct xs arbitrary: s) simp_all |
2934 by (induct xs arbitrary: s) simp_all |
2936 |
2935 |
2937 lemma foldr_conv_foldl: -- \<open>The ``Third Duality Theorem'' in Bird \& Wadler:\<close> |
2936 lemma foldr_conv_foldl: \<comment> \<open>The ``Third Duality Theorem'' in Bird \& Wadler:\<close> |
2938 "foldr f xs a = foldl (\<lambda>x y. f y x) a (rev xs)" |
2937 "foldr f xs a = foldl (\<lambda>x y. f y x) a (rev xs)" |
2939 by (simp add: foldr_conv_fold foldl_conv_fold) |
2938 by (simp add: foldr_conv_fold foldl_conv_fold) |
2940 |
2939 |
2941 lemma foldl_conv_foldr: |
2940 lemma foldl_conv_foldr: |
2942 "foldl f a xs = foldr (\<lambda>x y. f y x) (rev xs) a" |
2941 "foldl f a xs = foldr (\<lambda>x y. f y x) (rev xs) a" |
2998 apply(clarsimp simp add: append_eq_Cons_conv) |
2997 apply(clarsimp simp add: append_eq_Cons_conv) |
2999 apply arith |
2998 apply arith |
3000 done |
2999 done |
3001 |
3000 |
3002 lemma upt_Suc_append: "i <= j ==> [i..<(Suc j)] = [i..<j]@[j]" |
3001 lemma upt_Suc_append: "i <= j ==> [i..<(Suc j)] = [i..<j]@[j]" |
3003 -- \<open>Only needed if @{text upt_Suc} is deleted from the simpset.\<close> |
3002 \<comment> \<open>Only needed if \<open>upt_Suc\<close> is deleted from the simpset.\<close> |
3004 by simp |
3003 by simp |
3005 |
3004 |
3006 lemma upt_conv_Cons: "i < j ==> [i..<j] = i # [Suc i..<j]" |
3005 lemma upt_conv_Cons: "i < j ==> [i..<j] = i # [Suc i..<j]" |
3007 by (simp add: upt_rec) |
3006 by (simp add: upt_rec) |
3008 |
3007 |
3009 lemma upt_add_eq_append: "i<=j ==> [i..<j+k] = [i..<j]@[j..<j+k]" |
3008 lemma upt_add_eq_append: "i<=j ==> [i..<j+k] = [i..<j]@[j..<j+k]" |
3010 -- \<open>LOOPS as a simprule, since @{text "j <= j"}.\<close> |
3009 \<comment> \<open>LOOPS as a simprule, since \<open>j <= j\<close>.\<close> |
3011 by (induct k) auto |
3010 by (induct k) auto |
3012 |
3011 |
3013 lemma length_upt [simp]: "length [i..<j] = j - i" |
3012 lemma length_upt [simp]: "length [i..<j] = j - i" |
3014 by (induct j) (auto simp add: Suc_diff_le) |
3013 by (induct j) (auto simp add: Suc_diff_le) |
3015 |
3014 |
3078 apply (simp add: list_all2_conv_all_nth) |
3077 apply (simp add: list_all2_conv_all_nth) |
3079 apply (rule nth_equalityI, blast, simp) |
3078 apply (rule nth_equalityI, blast, simp) |
3080 done |
3079 done |
3081 |
3080 |
3082 lemma take_equalityI: "(\<forall>i. take i xs = take i ys) ==> xs = ys" |
3081 lemma take_equalityI: "(\<forall>i. take i xs = take i ys) ==> xs = ys" |
3083 -- \<open>The famous take-lemma.\<close> |
3082 \<comment> \<open>The famous take-lemma.\<close> |
3084 apply (drule_tac x = "max (length xs) (length ys)" in spec) |
3083 apply (drule_tac x = "max (length xs) (length ys)" in spec) |
3085 apply (simp add: le_max_iff_disj) |
3084 apply (simp add: le_max_iff_disj) |
3086 done |
3085 done |
3087 |
3086 |
3088 |
3087 |
3108 lemma nth_Cons_numeral [simp]: |
3107 lemma nth_Cons_numeral [simp]: |
3109 "(x # xs) ! numeral v = xs ! (numeral v - 1)" |
3108 "(x # xs) ! numeral v = xs ! (numeral v - 1)" |
3110 by (simp add: nth_Cons') |
3109 by (simp add: nth_Cons') |
3111 |
3110 |
3112 |
3111 |
3113 subsubsection \<open>@{text upto}: interval-list on @{typ int}\<close> |
3112 subsubsection \<open>\<open>upto\<close>: interval-list on @{typ int}\<close> |
3114 |
3113 |
3115 function upto :: "int \<Rightarrow> int \<Rightarrow> int list" ("(1[_../_])") where |
3114 function upto :: "int \<Rightarrow> int \<Rightarrow> int list" ("(1[_../_])") where |
3116 "upto i j = (if i \<le> j then i # [i+1..j] else [])" |
3115 "upto i j = (if i \<le> j then i # [i+1..j] else [])" |
3117 by auto |
3116 by auto |
3118 termination |
3117 termination |
5153 ultimately show "\<forall>i < length ?trans. ?trans ! i = ?map ! i" |
5152 ultimately show "\<forall>i < length ?trans. ?trans ! i = ?map ! i" |
5154 by (auto simp: nth_transpose intro: nth_equalityI) |
5153 by (auto simp: nth_transpose intro: nth_equalityI) |
5155 qed |
5154 qed |
5156 |
5155 |
5157 |
5156 |
5158 subsubsection \<open>@{text sorted_list_of_set}\<close> |
5157 subsubsection \<open>\<open>sorted_list_of_set\<close>\<close> |
5159 |
5158 |
5160 text\<open>This function maps (finite) linearly ordered sets to sorted |
5159 text\<open>This function maps (finite) linearly ordered sets to sorted |
5161 lists. Warning: in most cases it is not a good idea to convert from |
5160 lists. Warning: in most cases it is not a good idea to convert from |
5162 sets to lists but one should convert in the other direction (via |
5161 sets to lists but one should convert in the other direction (via |
5163 @{const set}).\<close> |
5162 @{const set}).\<close> |
5164 |
5163 |
5165 subsubsection \<open>@{text sorted_list_of_set}\<close> |
5164 subsubsection \<open>\<open>sorted_list_of_set\<close>\<close> |
5166 |
5165 |
5167 text\<open>This function maps (finite) linearly ordered sets to sorted |
5166 text\<open>This function maps (finite) linearly ordered sets to sorted |
5168 lists. Warning: in most cases it is not a good idea to convert from |
5167 lists. Warning: in most cases it is not a good idea to convert from |
5169 sets to lists but one should convert in the other direction (via |
5168 sets to lists but one should convert in the other direction (via |
5170 @{const set}).\<close> |
5169 @{const set}).\<close> |
5275 by (induct xs) auto |
5274 by (induct xs) auto |
5276 |
5275 |
5277 lemmas append_in_lists_conv [iff] = append_in_listsp_conv [to_set] |
5276 lemmas append_in_lists_conv [iff] = append_in_listsp_conv [to_set] |
5278 |
5277 |
5279 lemma in_listsp_conv_set: "(listsp A xs) = (\<forall>x \<in> set xs. A x)" |
5278 lemma in_listsp_conv_set: "(listsp A xs) = (\<forall>x \<in> set xs. A x)" |
5280 -- \<open>eliminate @{text listsp} in favour of @{text set}\<close> |
5279 \<comment> \<open>eliminate \<open>listsp\<close> in favour of \<open>set\<close>\<close> |
5281 by (induct xs) auto |
5280 by (induct xs) auto |
5282 |
5281 |
5283 lemmas in_lists_conv_set [code_unfold] = in_listsp_conv_set [to_set] |
5282 lemmas in_lists_conv_set [code_unfold] = in_listsp_conv_set [to_set] |
5284 |
5283 |
5285 lemma in_listspD [dest!]: "listsp A xs ==> \<forall>x\<in>set xs. A x" |
5284 lemma in_listspD [dest!]: "listsp A xs ==> \<forall>x\<in>set xs. A x" |
5324 done |
5323 done |
5325 |
5324 |
5326 |
5325 |
5327 subsubsection \<open>Lists as Cartesian products\<close> |
5326 subsubsection \<open>Lists as Cartesian products\<close> |
5328 |
5327 |
5329 text\<open>@{text"set_Cons A Xs"}: the set of lists with head drawn from |
5328 text\<open>\<open>set_Cons A Xs\<close>: the set of lists with head drawn from |
5330 @{term A} and tail drawn from @{term Xs}.\<close> |
5329 @{term A} and tail drawn from @{term Xs}.\<close> |
5331 |
5330 |
5332 definition set_Cons :: "'a set \<Rightarrow> 'a list set \<Rightarrow> 'a list set" where |
5331 definition set_Cons :: "'a set \<Rightarrow> 'a list set \<Rightarrow> 'a list set" where |
5333 "set_Cons A XS = {z. \<exists>x xs. z = x # xs \<and> x \<in> A \<and> xs \<in> XS}" |
5332 "set_Cons A XS = {z. \<exists>x xs. z = x # xs \<and> x \<in> A \<and> xs \<in> XS}" |
5334 |
5333 |
5348 subsubsection \<open>Length Lexicographic Ordering\<close> |
5347 subsubsection \<open>Length Lexicographic Ordering\<close> |
5349 |
5348 |
5350 text\<open>These orderings preserve well-foundedness: shorter lists |
5349 text\<open>These orderings preserve well-foundedness: shorter lists |
5351 precede longer lists. These ordering are not used in dictionaries.\<close> |
5350 precede longer lists. These ordering are not used in dictionaries.\<close> |
5352 |
5351 |
5353 primrec -- \<open>The lexicographic ordering for lists of the specified length\<close> |
5352 primrec \<comment> \<open>The lexicographic ordering for lists of the specified length\<close> |
5354 lexn :: "('a \<times> 'a) set \<Rightarrow> nat \<Rightarrow> ('a list \<times> 'a list) set" where |
5353 lexn :: "('a \<times> 'a) set \<Rightarrow> nat \<Rightarrow> ('a list \<times> 'a list) set" where |
5355 "lexn r 0 = {}" | |
5354 "lexn r 0 = {}" | |
5356 "lexn r (Suc n) = |
5355 "lexn r (Suc n) = |
5357 (map_prod (%(x, xs). x#xs) (%(x, xs). x#xs) ` (r <*lex*> lexn r n)) Int |
5356 (map_prod (%(x, xs). x#xs) (%(x, xs). x#xs) ` (r <*lex*> lexn r n)) Int |
5358 {(xs, ys). length xs = Suc n \<and> length ys = Suc n}" |
5357 {(xs, ys). length xs = Suc n \<and> length ys = Suc n}" |
5359 |
5358 |
5360 definition lex :: "('a \<times> 'a) set \<Rightarrow> ('a list \<times> 'a list) set" where |
5359 definition lex :: "('a \<times> 'a) set \<Rightarrow> ('a list \<times> 'a list) set" where |
5361 "lex r = (\<Union>n. lexn r n)" -- \<open>Holds only between lists of the same length\<close> |
5360 "lex r = (\<Union>n. lexn r n)" \<comment> \<open>Holds only between lists of the same length\<close> |
5362 |
5361 |
5363 definition lenlex :: "('a \<times> 'a) set => ('a list \<times> 'a list) set" where |
5362 definition lenlex :: "('a \<times> 'a) set => ('a list \<times> 'a list) set" where |
5364 "lenlex r = inv_image (less_than <*lex*> lex r) (\<lambda>xs. (length xs, xs))" |
5363 "lenlex r = inv_image (less_than <*lex*> lex r) (\<lambda>xs. (length xs, xs))" |
5365 -- \<open>Compares lists by their length and then lexicographically\<close> |
5364 \<comment> \<open>Compares lists by their length and then lexicographically\<close> |
5366 |
5365 |
5367 lemma wf_lexn: "wf r ==> wf (lexn r n)" |
5366 lemma wf_lexn: "wf r ==> wf (lexn r n)" |
5368 apply (induct n, simp, simp) |
5367 apply (induct n, simp, simp) |
5369 apply(rule wf_subset) |
5368 apply(rule wf_subset) |
5370 prefer 2 apply (rule Int_lower1) |
5369 prefer 2 apply (rule Int_lower1) |
5484 apply (rule_tac x="drop (Suc i) x" in exI) |
5483 apply (rule_tac x="drop (Suc i) x" in exI) |
5485 apply (drule sym, simp add: Cons_nth_drop_Suc) |
5484 apply (drule sym, simp add: Cons_nth_drop_Suc) |
5486 apply (rule_tac x="drop (Suc i) y" in exI) |
5485 apply (rule_tac x="drop (Suc i) y" in exI) |
5487 by (simp add: Cons_nth_drop_Suc) |
5486 by (simp add: Cons_nth_drop_Suc) |
5488 |
5487 |
5489 -- \<open>lexord is extension of partial ordering List.lex\<close> |
5488 \<comment> \<open>lexord is extension of partial ordering List.lex\<close> |
5490 lemma lexord_lex: "(x,y) \<in> lex r = ((x,y) \<in> lexord r \<and> length x = length y)" |
5489 lemma lexord_lex: "(x,y) \<in> lex r = ((x,y) \<in> lexord r \<and> length x = length y)" |
5491 apply (rule_tac x = y in spec) |
5490 apply (rule_tac x = y in spec) |
5492 apply (induct_tac x, clarsimp) |
5491 apply (induct_tac x, clarsimp) |
5493 by (clarify, case_tac x, simp, force) |
5492 by (clarify, case_tac x, simp, force) |
5494 |
5493 |
6157 |
6156 |
6158 definition member :: "'a list \<Rightarrow> 'a \<Rightarrow> bool" where |
6157 definition member :: "'a list \<Rightarrow> 'a \<Rightarrow> bool" where |
6159 [code_abbrev]: "member xs x \<longleftrightarrow> x \<in> set xs" |
6158 [code_abbrev]: "member xs x \<longleftrightarrow> x \<in> set xs" |
6160 |
6159 |
6161 text \<open> |
6160 text \<open> |
6162 Use @{text member} only for generating executable code. Otherwise use |
6161 Use \<open>member\<close> only for generating executable code. Otherwise use |
6163 @{prop "x \<in> set xs"} instead --- it is much easier to reason about. |
6162 @{prop "x \<in> set xs"} instead --- it is much easier to reason about. |
6164 \<close> |
6163 \<close> |
6165 |
6164 |
6166 lemma member_rec [code]: |
6165 lemma member_rec [code]: |
6167 "member (x # xs) y \<longleftrightarrow> x = y \<or> member xs y" |
6166 "member (x # xs) y \<longleftrightarrow> x = y \<or> member xs y" |
6182 |
6181 |
6183 definition list_ex1 :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where |
6182 definition list_ex1 :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where |
6184 list_ex1_iff [code_abbrev]: "list_ex1 P xs \<longleftrightarrow> (\<exists>! x. x \<in> set xs \<and> P x)" |
6183 list_ex1_iff [code_abbrev]: "list_ex1 P xs \<longleftrightarrow> (\<exists>! x. x \<in> set xs \<and> P x)" |
6185 |
6184 |
6186 text \<open> |
6185 text \<open> |
6187 Usually you should prefer @{text "\<forall>x\<in>set xs"}, @{text "\<exists>x\<in>set xs"} |
6186 Usually you should prefer \<open>\<forall>x\<in>set xs\<close>, \<open>\<exists>x\<in>set xs\<close> |
6188 and @{text "\<exists>!x. x\<in>set xs \<and> _"} over @{const list_all}, @{const list_ex} |
6187 and \<open>\<exists>!x. x\<in>set xs \<and> _\<close> over @{const list_all}, @{const list_ex} |
6189 and @{const list_ex1} in specifications. |
6188 and @{const list_ex1} in specifications. |
6190 \<close> |
6189 \<close> |
6191 |
6190 |
6192 lemma list_all_simps [code]: |
6191 lemma list_all_simps [code]: |
6193 "list_all P (x # xs) \<longleftrightarrow> P x \<and> list_all P xs" |
6192 "list_all P (x # xs) \<longleftrightarrow> P x \<and> list_all P xs" |
6420 |
6419 |
6421 lemma map_filter_map_filter [code_unfold]: |
6420 lemma map_filter_map_filter [code_unfold]: |
6422 "map f (filter P xs) = map_filter (\<lambda>x. if P x then Some (f x) else None) xs" |
6421 "map f (filter P xs) = map_filter (\<lambda>x. if P x then Some (f x) else None) xs" |
6423 by (simp add: map_filter_def) |
6422 by (simp add: map_filter_def) |
6424 |
6423 |
6425 text \<open>Optimized code for @{text"\<forall>i\<in>{a..b::int}"} and @{text"\<forall>n:{a..<b::nat}"} |
6424 text \<open>Optimized code for \<open>\<forall>i\<in>{a..b::int}\<close> and \<open>\<forall>n:{a..<b::nat}\<close> |
6426 and similiarly for @{text"\<exists>"}.\<close> |
6425 and similiarly for \<open>\<exists>\<close>.\<close> |
6427 |
6426 |
6428 definition all_interval_nat :: "(nat \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where |
6427 definition all_interval_nat :: "(nat \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where |
6429 "all_interval_nat P i j \<longleftrightarrow> (\<forall>n \<in> {i..<j}. P n)" |
6428 "all_interval_nat P i j \<longleftrightarrow> (\<forall>n \<in> {i..<j}. P n)" |
6430 |
6429 |
6431 lemma [code]: |
6430 lemma [code]: |