src/HOL/List.thy
changeset 37605 625bc011768a
parent 37465 fcc2c36b3770
child 37767 a2b7a20d6ea3
equal deleted inserted replaced
37604:1840dc0265da 37605:625bc011768a
  2350   case Nil then show ?case by simp
  2350   case Nil then show ?case by simp
  2351 next
  2351 next
  2352   case (Cons x xs) with assms show ?case by (simp add: foldl_fun_comm)
  2352   case (Cons x xs) with assms show ?case by (simp add: foldl_fun_comm)
  2353 qed
  2353 qed
  2354 
  2354 
       
  2355 lemma rev_foldl_cons [code]:
       
  2356   "rev xs = foldl (\<lambda>xs x. x # xs) [] xs"
       
  2357 proof (induct xs)
       
  2358   case Nil then show ?case by simp
       
  2359 next
       
  2360   case Cons
       
  2361   {
       
  2362     fix x xs ys
       
  2363     have "foldl (\<lambda>xs x. x # xs) ys xs @ [x]
       
  2364       = foldl (\<lambda>xs x. x # xs) (ys @ [x]) xs"
       
  2365     by (induct xs arbitrary: ys) auto
       
  2366   }
       
  2367   note aux = this
       
  2368   show ?case by (induct xs) (auto simp add: Cons aux)
       
  2369 qed
       
  2370 
  2355 
  2371 
  2356 text{* The ``First Duality Theorem'' in Bird \& Wadler: *}
  2372 text{* The ``First Duality Theorem'' in Bird \& Wadler: *}
  2357 
  2373 
  2358 lemma foldl_foldr1_lemma:
  2374 lemma foldl_foldr1_lemma:
  2359  "foldl op + a xs = a + foldr op + xs (0\<Colon>'a::monoid_add)"
  2375  "foldl op + a xs = a + foldr op + xs (0\<Colon>'a::monoid_add)"
  2505 
  2521 
  2506 lemma (in complete_lattice) SUPR_set_fold:
  2522 lemma (in complete_lattice) SUPR_set_fold:
  2507   "SUPR (set xs) f = foldl (\<lambda>y x. sup (f x) y) bot xs"
  2523   "SUPR (set xs) f = foldl (\<lambda>y x. sup (f x) y) bot xs"
  2508   unfolding SUPR_def set_map [symmetric] Sup_set_fold foldl_map
  2524   unfolding SUPR_def set_map [symmetric] Sup_set_fold foldl_map
  2509     by (simp add: sup_commute)
  2525     by (simp add: sup_commute)
  2510 
       
  2511 
       
  2512 subsubsection {* List summation: @{const listsum} and @{text"\<Sum>"}*}
       
  2513 
       
  2514 lemma listsum_append [simp]: "listsum (xs @ ys) = listsum xs + listsum ys"
       
  2515 by (induct xs) (simp_all add:add_assoc)
       
  2516 
       
  2517 lemma listsum_rev [simp]:
       
  2518   fixes xs :: "'a\<Colon>comm_monoid_add list"
       
  2519   shows "listsum (rev xs) = listsum xs"
       
  2520 by (induct xs) (simp_all add:add_ac)
       
  2521 
       
  2522 lemma listsum_map_remove1:
       
  2523 fixes f :: "'a \<Rightarrow> ('b::comm_monoid_add)"
       
  2524 shows "x : set xs \<Longrightarrow> listsum(map f xs) = f x + listsum(map f (remove1 x xs))"
       
  2525 by (induct xs)(auto simp add:add_ac)
       
  2526 
       
  2527 lemma list_size_conv_listsum:
       
  2528   "list_size f xs = listsum (map f xs) + size xs"
       
  2529 by(induct xs) auto
       
  2530 
       
  2531 lemma listsum_foldr: "listsum xs = foldr (op +) xs 0"
       
  2532 by (induct xs) auto
       
  2533 
       
  2534 lemma length_concat: "length (concat xss) = listsum (map length xss)"
       
  2535 by (induct xss) simp_all
       
  2536 
       
  2537 lemma listsum_map_filter:
       
  2538   fixes f :: "'a \<Rightarrow> 'b \<Colon> comm_monoid_add"
       
  2539   assumes "\<And> x. \<lbrakk> x \<in> set xs ; \<not> P x \<rbrakk> \<Longrightarrow> f x = 0"
       
  2540   shows "listsum (map f (filter P xs)) = listsum (map f xs)"
       
  2541 using assms by (induct xs) auto
       
  2542 
       
  2543 text{* For efficient code generation ---
       
  2544        @{const listsum} is not tail recursive but @{const foldl} is. *}
       
  2545 lemma listsum[code_unfold]: "listsum xs = foldl (op +) 0 xs"
       
  2546 by(simp add:listsum_foldr foldl_foldr1)
       
  2547 
       
  2548 lemma distinct_listsum_conv_Setsum:
       
  2549   "distinct xs \<Longrightarrow> listsum xs = Setsum(set xs)"
       
  2550 by (induct xs) simp_all
       
  2551 
       
  2552 lemma listsum_eq_0_nat_iff_nat[simp]:
       
  2553   "listsum ns = (0::nat) \<longleftrightarrow> (\<forall> n \<in> set ns. n = 0)"
       
  2554 by(simp add: listsum)
       
  2555 
       
  2556 lemma elem_le_listsum_nat: "k<size ns \<Longrightarrow> ns!k <= listsum(ns::nat list)"
       
  2557 apply(induct ns arbitrary: k)
       
  2558  apply simp
       
  2559 apply(fastsimp simp add:nth_Cons split: nat.split)
       
  2560 done
       
  2561 
       
  2562 lemma listsum_update_nat: "k<size ns \<Longrightarrow>
       
  2563   listsum (ns[k := (n::nat)]) = listsum ns + n - ns!k"
       
  2564 apply(induct ns arbitrary:k)
       
  2565  apply (auto split:nat.split)
       
  2566 apply(drule elem_le_listsum_nat)
       
  2567 apply arith
       
  2568 done
       
  2569 
       
  2570 text{* Some syntactic sugar for summing a function over a list: *}
       
  2571 
       
  2572 syntax
       
  2573   "_listsum" :: "pttrn => 'a list => 'b => 'b"    ("(3SUM _<-_. _)" [0, 51, 10] 10)
       
  2574 syntax (xsymbols)
       
  2575   "_listsum" :: "pttrn => 'a list => 'b => 'b"    ("(3\<Sum>_\<leftarrow>_. _)" [0, 51, 10] 10)
       
  2576 syntax (HTML output)
       
  2577   "_listsum" :: "pttrn => 'a list => 'b => 'b"    ("(3\<Sum>_\<leftarrow>_. _)" [0, 51, 10] 10)
       
  2578 
       
  2579 translations -- {* Beware of argument permutation! *}
       
  2580   "SUM x<-xs. b" == "CONST listsum (CONST map (%x. b) xs)"
       
  2581   "\<Sum>x\<leftarrow>xs. b" == "CONST listsum (CONST map (%x. b) xs)"
       
  2582 
       
  2583 lemma listsum_triv: "(\<Sum>x\<leftarrow>xs. r) = of_nat (length xs) * r"
       
  2584   by (induct xs) (simp_all add: left_distrib)
       
  2585 
       
  2586 lemma listsum_0 [simp]: "(\<Sum>x\<leftarrow>xs. 0) = 0"
       
  2587   by (induct xs) (simp_all add: left_distrib)
       
  2588 
       
  2589 text{* For non-Abelian groups @{text xs} needs to be reversed on one side: *}
       
  2590 lemma uminus_listsum_map:
       
  2591   fixes f :: "'a \<Rightarrow> 'b\<Colon>ab_group_add"
       
  2592   shows "- listsum (map f xs) = (listsum (map (uminus o f) xs))"
       
  2593 by (induct xs) simp_all
       
  2594 
       
  2595 lemma listsum_addf:
       
  2596   fixes f g :: "'a \<Rightarrow> 'b::comm_monoid_add"
       
  2597   shows "(\<Sum>x\<leftarrow>xs. f x + g x) = listsum (map f xs) + listsum (map g xs)"
       
  2598 by (induct xs) (simp_all add: algebra_simps)
       
  2599 
       
  2600 lemma listsum_subtractf:
       
  2601   fixes f g :: "'a \<Rightarrow> 'b::ab_group_add"
       
  2602   shows "(\<Sum>x\<leftarrow>xs. f x - g x) = listsum (map f xs) - listsum (map g xs)"
       
  2603 by (induct xs) simp_all
       
  2604 
       
  2605 lemma listsum_const_mult:
       
  2606   fixes f :: "'a \<Rightarrow> 'b::semiring_0"
       
  2607   shows "(\<Sum>x\<leftarrow>xs. c * f x) = c * (\<Sum>x\<leftarrow>xs. f x)"
       
  2608 by (induct xs, simp_all add: algebra_simps)
       
  2609 
       
  2610 lemma listsum_mult_const:
       
  2611   fixes f :: "'a \<Rightarrow> 'b::semiring_0"
       
  2612   shows "(\<Sum>x\<leftarrow>xs. f x * c) = (\<Sum>x\<leftarrow>xs. f x) * c"
       
  2613 by (induct xs, simp_all add: algebra_simps)
       
  2614 
       
  2615 lemma listsum_abs:
       
  2616   fixes xs :: "'a::ordered_ab_group_add_abs list"
       
  2617   shows "\<bar>listsum xs\<bar> \<le> listsum (map abs xs)"
       
  2618 by (induct xs, simp, simp add: order_trans [OF abs_triangle_ineq])
       
  2619 
       
  2620 lemma listsum_mono:
       
  2621   fixes f g :: "'a \<Rightarrow> 'b::{comm_monoid_add, ordered_ab_semigroup_add}"
       
  2622   shows "(\<And>x. x \<in> set xs \<Longrightarrow> f x \<le> g x) \<Longrightarrow> (\<Sum>x\<leftarrow>xs. f x) \<le> (\<Sum>x\<leftarrow>xs. g x)"
       
  2623 by (induct xs, simp, simp add: add_mono)
       
  2624 
  2526 
  2625 
  2527 
  2626 subsubsection {* @{text upt} *}
  2528 subsubsection {* @{text upt} *}
  2627 
  2529 
  2628 lemma upt_rec[code]: "[i..<j] = (if i<j then i#[Suc i..<j] else [])"
  2530 lemma upt_rec[code]: "[i..<j] = (if i<j then i#[Suc i..<j] else [])"
  2957   shows "distinct (butlast xs)"
  2859   shows "distinct (butlast xs)"
  2958 proof -
  2860 proof -
  2959   from `xs \<noteq> []` obtain ys y where "xs = ys @ [y]" by (cases xs rule: rev_cases) auto
  2861   from `xs \<noteq> []` obtain ys y where "xs = ys @ [y]" by (cases xs rule: rev_cases) auto
  2960   with `distinct xs` show ?thesis by simp
  2862   with `distinct xs` show ?thesis by simp
  2961 qed
  2863 qed
       
  2864 
       
  2865 
       
  2866 subsubsection {* List summation: @{const listsum} and @{text"\<Sum>"}*}
       
  2867 
       
  2868 lemma listsum_append [simp]: "listsum (xs @ ys) = listsum xs + listsum ys"
       
  2869 by (induct xs) (simp_all add:add_assoc)
       
  2870 
       
  2871 lemma listsum_rev [simp]:
       
  2872   fixes xs :: "'a\<Colon>comm_monoid_add list"
       
  2873   shows "listsum (rev xs) = listsum xs"
       
  2874 by (induct xs) (simp_all add:add_ac)
       
  2875 
       
  2876 lemma listsum_map_remove1:
       
  2877 fixes f :: "'a \<Rightarrow> ('b::comm_monoid_add)"
       
  2878 shows "x : set xs \<Longrightarrow> listsum(map f xs) = f x + listsum(map f (remove1 x xs))"
       
  2879 by (induct xs)(auto simp add:add_ac)
       
  2880 
       
  2881 lemma list_size_conv_listsum:
       
  2882   "list_size f xs = listsum (map f xs) + size xs"
       
  2883 by(induct xs) auto
       
  2884 
       
  2885 lemma listsum_foldr: "listsum xs = foldr (op +) xs 0"
       
  2886 by (induct xs) auto
       
  2887 
       
  2888 lemma length_concat: "length (concat xss) = listsum (map length xss)"
       
  2889 by (induct xss) simp_all
       
  2890 
       
  2891 lemma listsum_map_filter:
       
  2892   fixes f :: "'a \<Rightarrow> 'b \<Colon> comm_monoid_add"
       
  2893   assumes "\<And> x. \<lbrakk> x \<in> set xs ; \<not> P x \<rbrakk> \<Longrightarrow> f x = 0"
       
  2894   shows "listsum (map f (filter P xs)) = listsum (map f xs)"
       
  2895 using assms by (induct xs) auto
       
  2896 
       
  2897 text{* For efficient code generation ---
       
  2898        @{const listsum} is not tail recursive but @{const foldl} is. *}
       
  2899 lemma listsum[code_unfold]: "listsum xs = foldl (op +) 0 xs"
       
  2900 by(simp add:listsum_foldr foldl_foldr1)
       
  2901 
       
  2902 lemma distinct_listsum_conv_Setsum:
       
  2903   "distinct xs \<Longrightarrow> listsum xs = Setsum(set xs)"
       
  2904 by (induct xs) simp_all
       
  2905 
       
  2906 lemma listsum_eq_0_nat_iff_nat[simp]:
       
  2907   "listsum ns = (0::nat) \<longleftrightarrow> (\<forall> n \<in> set ns. n = 0)"
       
  2908 by(simp add: listsum)
       
  2909 
       
  2910 lemma elem_le_listsum_nat: "k<size ns \<Longrightarrow> ns!k <= listsum(ns::nat list)"
       
  2911 apply(induct ns arbitrary: k)
       
  2912  apply simp
       
  2913 apply(fastsimp simp add:nth_Cons split: nat.split)
       
  2914 done
       
  2915 
       
  2916 lemma listsum_update_nat: "k<size ns \<Longrightarrow>
       
  2917   listsum (ns[k := (n::nat)]) = listsum ns + n - ns!k"
       
  2918 apply(induct ns arbitrary:k)
       
  2919  apply (auto split:nat.split)
       
  2920 apply(drule elem_le_listsum_nat)
       
  2921 apply arith
       
  2922 done
       
  2923 
       
  2924 text{* Some syntactic sugar for summing a function over a list: *}
       
  2925 
       
  2926 syntax
       
  2927   "_listsum" :: "pttrn => 'a list => 'b => 'b"    ("(3SUM _<-_. _)" [0, 51, 10] 10)
       
  2928 syntax (xsymbols)
       
  2929   "_listsum" :: "pttrn => 'a list => 'b => 'b"    ("(3\<Sum>_\<leftarrow>_. _)" [0, 51, 10] 10)
       
  2930 syntax (HTML output)
       
  2931   "_listsum" :: "pttrn => 'a list => 'b => 'b"    ("(3\<Sum>_\<leftarrow>_. _)" [0, 51, 10] 10)
       
  2932 
       
  2933 translations -- {* Beware of argument permutation! *}
       
  2934   "SUM x<-xs. b" == "CONST listsum (CONST map (%x. b) xs)"
       
  2935   "\<Sum>x\<leftarrow>xs. b" == "CONST listsum (CONST map (%x. b) xs)"
       
  2936 
       
  2937 lemma listsum_triv: "(\<Sum>x\<leftarrow>xs. r) = of_nat (length xs) * r"
       
  2938   by (induct xs) (simp_all add: left_distrib)
       
  2939 
       
  2940 lemma listsum_0 [simp]: "(\<Sum>x\<leftarrow>xs. 0) = 0"
       
  2941   by (induct xs) (simp_all add: left_distrib)
       
  2942 
       
  2943 text{* For non-Abelian groups @{text xs} needs to be reversed on one side: *}
       
  2944 lemma uminus_listsum_map:
       
  2945   fixes f :: "'a \<Rightarrow> 'b\<Colon>ab_group_add"
       
  2946   shows "- listsum (map f xs) = (listsum (map (uminus o f) xs))"
       
  2947 by (induct xs) simp_all
       
  2948 
       
  2949 lemma listsum_addf:
       
  2950   fixes f g :: "'a \<Rightarrow> 'b::comm_monoid_add"
       
  2951   shows "(\<Sum>x\<leftarrow>xs. f x + g x) = listsum (map f xs) + listsum (map g xs)"
       
  2952 by (induct xs) (simp_all add: algebra_simps)
       
  2953 
       
  2954 lemma listsum_subtractf:
       
  2955   fixes f g :: "'a \<Rightarrow> 'b::ab_group_add"
       
  2956   shows "(\<Sum>x\<leftarrow>xs. f x - g x) = listsum (map f xs) - listsum (map g xs)"
       
  2957 by (induct xs) simp_all
       
  2958 
       
  2959 lemma listsum_const_mult:
       
  2960   fixes f :: "'a \<Rightarrow> 'b::semiring_0"
       
  2961   shows "(\<Sum>x\<leftarrow>xs. c * f x) = c * (\<Sum>x\<leftarrow>xs. f x)"
       
  2962 by (induct xs, simp_all add: algebra_simps)
       
  2963 
       
  2964 lemma listsum_mult_const:
       
  2965   fixes f :: "'a \<Rightarrow> 'b::semiring_0"
       
  2966   shows "(\<Sum>x\<leftarrow>xs. f x * c) = (\<Sum>x\<leftarrow>xs. f x) * c"
       
  2967 by (induct xs, simp_all add: algebra_simps)
       
  2968 
       
  2969 lemma listsum_abs:
       
  2970   fixes xs :: "'a::ordered_ab_group_add_abs list"
       
  2971   shows "\<bar>listsum xs\<bar> \<le> listsum (map abs xs)"
       
  2972 by (induct xs, simp, simp add: order_trans [OF abs_triangle_ineq])
       
  2973 
       
  2974 lemma listsum_mono:
       
  2975   fixes f g :: "'a \<Rightarrow> 'b::{comm_monoid_add, ordered_ab_semigroup_add}"
       
  2976   shows "(\<And>x. x \<in> set xs \<Longrightarrow> f x \<le> g x) \<Longrightarrow> (\<Sum>x\<leftarrow>xs. f x) \<le> (\<Sum>x\<leftarrow>xs. g x)"
       
  2977 by (induct xs, simp, simp add: add_mono)
       
  2978 
       
  2979 lemma listsum_distinct_conv_setsum_set:
       
  2980   "distinct xs \<Longrightarrow> listsum (map f xs) = setsum f (set xs)"
       
  2981   by (induct xs) simp_all
       
  2982 
       
  2983 lemma interv_listsum_conv_setsum_set_nat:
       
  2984   "listsum (map f [m..<n]) = setsum f (set [m..<n])"
       
  2985   by (simp add: listsum_distinct_conv_setsum_set)
       
  2986 
       
  2987 lemma interv_listsum_conv_setsum_set_int:
       
  2988   "listsum (map f [k..l]) = setsum f (set [k..l])"
       
  2989   by (simp add: listsum_distinct_conv_setsum_set)
       
  2990 
       
  2991 text {* General equivalence between @{const listsum} and @{const setsum} *}
       
  2992 lemma listsum_setsum_nth:
       
  2993   "listsum xs = (\<Sum> i = 0 ..< length xs. xs ! i)"
       
  2994   using interv_listsum_conv_setsum_set_nat [of "op ! xs" 0 "length xs"] by (simp add: map_nth)
  2962 
  2995 
  2963 
  2996 
  2964 subsubsection {* @{const insert} *}
  2997 subsubsection {* @{const insert} *}
  2965 
  2998 
  2966 lemma in_set_insert [simp]:
  2999 lemma in_set_insert [simp]:
  4511 lemma transfer_nat_int_fold1: "fold f l x =
  4544 lemma transfer_nat_int_fold1: "fold f l x =
  4512     fold (%x. f (nat x)) (embed_list l) x";
  4545     fold (%x. f (nat x)) (embed_list l) x";
  4513 *)
  4546 *)
  4514 
  4547 
  4515 
  4548 
  4516 subsection {* Code generator *}
  4549 subsection {* Code generation *}
  4517 
  4550 
  4518 subsubsection {* Setup *}
  4551 subsubsection {* Counterparts for set-related operations *}
       
  4552 
       
  4553 definition member :: "'a list \<Rightarrow> 'a \<Rightarrow> bool" where
       
  4554   [code_post]: "member xs x \<longleftrightarrow> x \<in> set xs"
       
  4555 
       
  4556 text {*
       
  4557   Only use @{text member} for generating executable code.  Otherwise use
       
  4558   @{prop "x \<in> set xs"} instead --- it is much easier to reason about.
       
  4559 *}
       
  4560 
       
  4561 lemma member_set:
       
  4562   "member = set"
       
  4563   by (simp add: expand_fun_eq member_def mem_def)
       
  4564 
       
  4565 lemma member_rec [code]:
       
  4566   "member (x # xs) y \<longleftrightarrow> x = y \<or> member xs y"
       
  4567   "member [] y \<longleftrightarrow> False"
       
  4568   by (auto simp add: member_def)
       
  4569 
       
  4570 lemma in_set_member [code_unfold]:
       
  4571   "x \<in> set xs \<longleftrightarrow> member xs x"
       
  4572   by (simp add: member_def)
       
  4573 
       
  4574 declare INFI_def [code_unfold]
       
  4575 declare SUPR_def [code_unfold]
       
  4576 
       
  4577 declare set_map [symmetric, code_unfold]
       
  4578 
       
  4579 definition list_all :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where
       
  4580   list_all_iff [code_post]: "list_all P xs \<longleftrightarrow> (\<forall>x \<in> set xs. P x)"
       
  4581 
       
  4582 definition list_ex :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where
       
  4583   list_ex_iff [code_post]: "list_ex P xs \<longleftrightarrow> (\<exists>x \<in> set xs. P x)"
       
  4584 
       
  4585 text {*
       
  4586   Usually you should prefer @{text "\<forall>x\<in>set xs"} and @{text "\<exists>x\<in>set xs"}
       
  4587   over @{const list_all} and @{const list_ex} in specifications.
       
  4588 *}
       
  4589 
       
  4590 lemma list_all_simps [simp, code]:
       
  4591   "list_all P (x # xs) \<longleftrightarrow> P x \<and> list_all P xs"
       
  4592   "list_all P [] \<longleftrightarrow> True"
       
  4593   by (simp_all add: list_all_iff)
       
  4594 
       
  4595 lemma list_ex_simps [simp, code]:
       
  4596   "list_ex P (x # xs) \<longleftrightarrow> P x \<or> list_ex P xs"
       
  4597   "list_ex P [] \<longleftrightarrow> False"
       
  4598   by (simp_all add: list_ex_iff)
       
  4599 
       
  4600 lemma Ball_set_list_all [code_unfold]:
       
  4601   "Ball (set xs) P \<longleftrightarrow> list_all P xs"
       
  4602   by (simp add: list_all_iff)
       
  4603 
       
  4604 lemma Bex_set_list_ex [code_unfold]:
       
  4605   "Bex (set xs) P \<longleftrightarrow> list_ex P xs"
       
  4606   by (simp add: list_ex_iff)
       
  4607 
       
  4608 lemma list_all_append [simp]:
       
  4609   "list_all P (xs @ ys) \<longleftrightarrow> list_all P xs \<and> list_all P ys"
       
  4610   by (auto simp add: list_all_iff)
       
  4611 
       
  4612 lemma list_ex_append [simp]:
       
  4613   "list_ex P (xs @ ys) \<longleftrightarrow> list_ex P xs \<or> list_ex P ys"
       
  4614   by (auto simp add: list_ex_iff)
       
  4615 
       
  4616 lemma list_all_rev [simp]:
       
  4617   "list_all P (rev xs) \<longleftrightarrow> list_all P xs"
       
  4618   by (simp add: list_all_iff)
       
  4619 
       
  4620 lemma list_ex_rev [simp]:
       
  4621   "list_ex P (rev xs) \<longleftrightarrow> list_ex P xs"
       
  4622   by (simp add: list_ex_iff)
       
  4623 
       
  4624 lemma list_all_length:
       
  4625   "list_all P xs \<longleftrightarrow> (\<forall>n < length xs. P (xs ! n))"
       
  4626   by (auto simp add: list_all_iff set_conv_nth)
       
  4627 
       
  4628 lemma list_ex_length:
       
  4629   "list_ex P xs \<longleftrightarrow> (\<exists>n < length xs. P (xs ! n))"
       
  4630   by (auto simp add: list_ex_iff set_conv_nth)
       
  4631 
       
  4632 lemma list_all_cong [fundef_cong]:
       
  4633   "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> f x = g x) \<Longrightarrow> list_all f xs = list_all g ys"
       
  4634   by (simp add: list_all_iff)
       
  4635 
       
  4636 lemma list_any_cong [fundef_cong]:
       
  4637   "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> f x = g x) \<Longrightarrow> list_ex f xs = list_ex g ys"
       
  4638   by (simp add: list_ex_iff)
       
  4639 
       
  4640 text {* Bounded quantification and summation over nats. *}
       
  4641 
       
  4642 lemma atMost_upto [code_unfold]:
       
  4643   "{..n} = set [0..<Suc n]"
       
  4644   by auto
       
  4645 
       
  4646 lemma atLeast_upt [code_unfold]:
       
  4647   "{..<n} = set [0..<n]"
       
  4648   by auto
       
  4649 
       
  4650 lemma greaterThanLessThan_upt [code_unfold]:
       
  4651   "{n<..<m} = set [Suc n..<m]"
       
  4652   by auto
       
  4653 
       
  4654 lemmas atLeastLessThan_upt [code_unfold] = set_upt [symmetric]
       
  4655 
       
  4656 lemma greaterThanAtMost_upt [code_unfold]:
       
  4657   "{n<..m} = set [Suc n..<Suc m]"
       
  4658   by auto
       
  4659 
       
  4660 lemma atLeastAtMost_upt [code_unfold]:
       
  4661   "{n..m} = set [n..<Suc m]"
       
  4662   by auto
       
  4663 
       
  4664 lemma all_nat_less_eq [code_unfold]:
       
  4665   "(\<forall>m<n\<Colon>nat. P m) \<longleftrightarrow> (\<forall>m \<in> {0..<n}. P m)"
       
  4666   by auto
       
  4667 
       
  4668 lemma ex_nat_less_eq [code_unfold]:
       
  4669   "(\<exists>m<n\<Colon>nat. P m) \<longleftrightarrow> (\<exists>m \<in> {0..<n}. P m)"
       
  4670   by auto
       
  4671 
       
  4672 lemma all_nat_less [code_unfold]:
       
  4673   "(\<forall>m\<le>n\<Colon>nat. P m) \<longleftrightarrow> (\<forall>m \<in> {0..n}. P m)"
       
  4674   by auto
       
  4675 
       
  4676 lemma ex_nat_less [code_unfold]:
       
  4677   "(\<exists>m\<le>n\<Colon>nat. P m) \<longleftrightarrow> (\<exists>m \<in> {0..n}. P m)"
       
  4678   by auto
       
  4679 
       
  4680 lemma setsum_set_upt_conv_listsum_nat [code_unfold]:
       
  4681   "setsum f (set [m..<n]) = listsum (map f [m..<n])"
       
  4682   by (simp add: interv_listsum_conv_setsum_set_nat)
       
  4683 
       
  4684 text {* Summation over ints. *}
       
  4685 
       
  4686 lemma greaterThanLessThan_upto [code_unfold]:
       
  4687   "{i<..<j::int} = set [i+1..j - 1]"
       
  4688 by auto
       
  4689 
       
  4690 lemma atLeastLessThan_upto [code_unfold]:
       
  4691   "{i..<j::int} = set [i..j - 1]"
       
  4692 by auto
       
  4693 
       
  4694 lemma greaterThanAtMost_upto [code_unfold]:
       
  4695   "{i<..j::int} = set [i+1..j]"
       
  4696 by auto
       
  4697 
       
  4698 lemmas atLeastAtMost_upto [code_unfold] = set_upto [symmetric]
       
  4699 
       
  4700 lemma setsum_set_upto_conv_listsum_int [code_unfold]:
       
  4701   "setsum f (set [i..j::int]) = listsum (map f [i..j])"
       
  4702   by (simp add: interv_listsum_conv_setsum_set_int)
       
  4703 
       
  4704 
       
  4705 subsubsection {* Optimizing by rewriting *}
       
  4706 
       
  4707 definition null :: "'a list \<Rightarrow> bool" where
       
  4708   [code_post]: "null xs \<longleftrightarrow> xs = []"
       
  4709 
       
  4710 text {*
       
  4711   Efficient emptyness check is implemented by @{const null}.
       
  4712 *}
       
  4713 
       
  4714 lemma null_rec [code]:
       
  4715   "null (x # xs) \<longleftrightarrow> False"
       
  4716   "null [] \<longleftrightarrow> True"
       
  4717   by (simp_all add: null_def)
       
  4718 
       
  4719 lemma eq_Nil_null [code_unfold]:
       
  4720   "xs = [] \<longleftrightarrow> null xs"
       
  4721   by (simp add: null_def)
       
  4722 
       
  4723 lemma equal_Nil_null [code_unfold]:
       
  4724   "eq_class.eq xs [] \<longleftrightarrow> null xs"
       
  4725   by (simp add: eq eq_Nil_null)
       
  4726 
       
  4727 definition maps :: "('a \<Rightarrow> 'b list) \<Rightarrow> 'a list \<Rightarrow> 'b list" where
       
  4728   [code_post]: "maps f xs = concat (map f xs)"
       
  4729 
       
  4730 definition map_filter :: "('a \<Rightarrow> 'b option) \<Rightarrow> 'a list \<Rightarrow> 'b list" where
       
  4731   [code_post]: "map_filter f xs = map (the \<circ> f) (filter (\<lambda>x. f x \<noteq> None) xs)"
       
  4732 
       
  4733 text {*
       
  4734   Operations @{const maps} and @{const map_filter} avoid
       
  4735   intermediate lists on execution -- do not use for proving.
       
  4736 *}
       
  4737 
       
  4738 lemma maps_simps [code]:
       
  4739   "maps f (x # xs) = f x @ maps f xs"
       
  4740   "maps f [] = []"
       
  4741   by (simp_all add: maps_def)
       
  4742 
       
  4743 lemma map_filter_simps [code]:
       
  4744   "map_filter f (x # xs) = (case f x of None \<Rightarrow> map_filter f xs | Some y \<Rightarrow> y # map_filter f xs)"
       
  4745   "map_filter f [] = []"
       
  4746   by (simp_all add: map_filter_def split: option.split)
       
  4747 
       
  4748 lemma concat_map_maps [code_unfold]:
       
  4749   "concat (map f xs) = maps f xs"
       
  4750   by (simp add: maps_def)
       
  4751 
       
  4752 lemma map_filter_map_filter [code_unfold]:
       
  4753   "map f (filter P xs) = map_filter (\<lambda>x. if P x then Some (f x) else None) xs"
       
  4754   by (simp add: map_filter_def)
       
  4755 
       
  4756 text {* Optimized code for @{text"\<forall>i\<in>{a..b::int}"} and @{text"\<forall>n:{a..<b::nat}"}
       
  4757 and similiarly for @{text"\<exists>"}. *}
       
  4758 
       
  4759 definition all_interval_nat :: "(nat \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where
       
  4760   "all_interval_nat P i j \<longleftrightarrow> (\<forall>n \<in> {i..<j}. P n)"
       
  4761 
       
  4762 lemma [code]:
       
  4763   "all_interval_nat P i j \<longleftrightarrow> i \<ge> j \<or> P i \<and> all_interval_nat P (Suc i) j"
       
  4764 proof -
       
  4765   have *: "\<And>n. P i \<Longrightarrow> \<forall>n\<in>{Suc i..<j}. P n \<Longrightarrow> i \<le> n \<Longrightarrow> n < j \<Longrightarrow> P n"
       
  4766   proof -
       
  4767     fix n
       
  4768     assume "P i" "\<forall>n\<in>{Suc i..<j}. P n" "i \<le> n" "n < j"
       
  4769     then show "P n" by (cases "n = i") simp_all
       
  4770   qed
       
  4771   show ?thesis by (auto simp add: all_interval_nat_def intro: *)
       
  4772 qed
       
  4773 
       
  4774 lemma list_all_iff_all_interval_nat [code_unfold]:
       
  4775   "list_all P [i..<j] \<longleftrightarrow> all_interval_nat P i j"
       
  4776   by (simp add: list_all_iff all_interval_nat_def)
       
  4777 
       
  4778 lemma list_ex_iff_not_all_inverval_nat [code_unfold]:
       
  4779   "list_ex P [i..<j] \<longleftrightarrow> \<not> (all_interval_nat (Not \<circ> P) i j)"
       
  4780   by (simp add: list_ex_iff all_interval_nat_def)
       
  4781 
       
  4782 definition all_interval_int :: "(int \<Rightarrow> bool) \<Rightarrow> int \<Rightarrow> int \<Rightarrow> bool" where
       
  4783   "all_interval_int P i j \<longleftrightarrow> (\<forall>k \<in> {i..j}. P k)"
       
  4784 
       
  4785 lemma [code]:
       
  4786   "all_interval_int P i j \<longleftrightarrow> i > j \<or> P i \<and> all_interval_int P (i + 1) j"
       
  4787 proof -
       
  4788   have *: "\<And>k. P i \<Longrightarrow> \<forall>k\<in>{i+1..j}. P k \<Longrightarrow> i \<le> k \<Longrightarrow> k \<le> j \<Longrightarrow> P k"
       
  4789   proof -
       
  4790     fix k
       
  4791     assume "P i" "\<forall>k\<in>{i+1..j}. P k" "i \<le> k" "k \<le> j"
       
  4792     then show "P k" by (cases "k = i") simp_all
       
  4793   qed
       
  4794   show ?thesis by (auto simp add: all_interval_int_def intro: *)
       
  4795 qed
       
  4796 
       
  4797 lemma list_all_iff_all_interval_int [code_unfold]:
       
  4798   "list_all P [i..j] \<longleftrightarrow> all_interval_int P i j"
       
  4799   by (simp add: list_all_iff all_interval_int_def)
       
  4800 
       
  4801 lemma list_ex_iff_not_all_inverval_int [code_unfold]:
       
  4802   "list_ex P [i..j] \<longleftrightarrow> \<not> (all_interval_int (Not \<circ> P) i j)"
       
  4803   by (simp add: list_ex_iff all_interval_int_def)
       
  4804 
       
  4805 hide_const (open) member null maps map_filter all_interval_nat all_interval_int
       
  4806 
       
  4807 
       
  4808 subsubsection {* Pretty lists *}
  4519 
  4809 
  4520 use "Tools/list_code.ML"
  4810 use "Tools/list_code.ML"
  4521 
  4811 
  4522 code_type list
  4812 code_type list
  4523   (SML "_ list")
  4813   (SML "_ list")
  4576   #> Codegen.add_codegen "list_codegen" list_codegen
  4866   #> Codegen.add_codegen "list_codegen" list_codegen
  4577 end
  4867 end
  4578 *}
  4868 *}
  4579 
  4869 
  4580 
  4870 
  4581 subsubsection {* Generation of efficient code *}
       
  4582 
       
  4583 definition member :: "'a list \<Rightarrow> 'a \<Rightarrow> bool" where
       
  4584   mem_iff [code_post]: "member xs x \<longleftrightarrow> x \<in> set xs"
       
  4585 
       
  4586 primrec
       
  4587   null:: "'a list \<Rightarrow> bool"
       
  4588 where
       
  4589   "null [] = True"
       
  4590   | "null (x#xs) = False"
       
  4591 
       
  4592 primrec
       
  4593   list_inter :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list"
       
  4594 where
       
  4595   "list_inter [] bs = []"
       
  4596   | "list_inter (a#as) bs =
       
  4597      (if a \<in> set bs then a # list_inter as bs else list_inter as bs)"
       
  4598 
       
  4599 primrec
       
  4600   list_all :: "('a \<Rightarrow> bool) \<Rightarrow> ('a list \<Rightarrow> bool)"
       
  4601 where
       
  4602   "list_all P [] = True"
       
  4603   | "list_all P (x#xs) = (P x \<and> list_all P xs)"
       
  4604 
       
  4605 primrec
       
  4606   list_ex :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool"
       
  4607 where
       
  4608   "list_ex P [] = False"
       
  4609   | "list_ex P (x#xs) = (P x \<or> list_ex P xs)"
       
  4610 
       
  4611 primrec
       
  4612   filtermap :: "('a \<Rightarrow> 'b option) \<Rightarrow> 'a list \<Rightarrow> 'b list"
       
  4613 where
       
  4614   "filtermap f [] = []"
       
  4615   | "filtermap f (x#xs) =
       
  4616      (case f x of None \<Rightarrow> filtermap f xs
       
  4617       | Some y \<Rightarrow> y # filtermap f xs)"
       
  4618 
       
  4619 primrec
       
  4620   map_filter :: "('a \<Rightarrow> 'b) \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'b list"
       
  4621 where
       
  4622   "map_filter f P [] = []"
       
  4623   | "map_filter f P (x#xs) =
       
  4624      (if P x then f x # map_filter f P xs else map_filter f P xs)"
       
  4625 
       
  4626 primrec
       
  4627   length_unique :: "'a list \<Rightarrow> nat"
       
  4628 where
       
  4629   "length_unique [] = 0"
       
  4630   | "length_unique (x#xs) =
       
  4631       (if x \<in> set xs then length_unique xs else Suc (length_unique xs))"
       
  4632 
       
  4633 primrec
       
  4634   concat_map :: "('a => 'b list) => 'a list => 'b list"
       
  4635 where
       
  4636   "concat_map f [] = []"
       
  4637   | "concat_map f (x#xs) = f x @ concat_map f xs"
       
  4638 
       
  4639 text {*
       
  4640   Only use @{text member} for generating executable code.  Otherwise use
       
  4641   @{prop "x : set xs"} instead --- it is much easier to reason about.
       
  4642   The same is true for @{const list_all} and @{const list_ex}: write
       
  4643   @{text "\<forall>x\<in>set xs"} and @{text "\<exists>x\<in>set xs"} instead because the HOL
       
  4644   quantifiers are aleady known to the automatic provers. In fact, the
       
  4645   declarations in the code subsection make sure that @{text "\<in>"},
       
  4646   @{text "\<forall>x\<in>set xs"} and @{text "\<exists>x\<in>set xs"} are implemented
       
  4647   efficiently.
       
  4648 
       
  4649   Efficient emptyness check is implemented by @{const null}.
       
  4650 
       
  4651   The functions @{const filtermap} and @{const map_filter} are just
       
  4652   there to generate efficient code. Do not use
       
  4653   them for modelling and proving.
       
  4654 *}
       
  4655 
       
  4656 lemma rev_foldl_cons [code]:
       
  4657   "rev xs = foldl (\<lambda>xs x. x # xs) [] xs"
       
  4658 proof (induct xs)
       
  4659   case Nil then show ?case by simp
       
  4660 next
       
  4661   case Cons
       
  4662   {
       
  4663     fix x xs ys
       
  4664     have "foldl (\<lambda>xs x. x # xs) ys xs @ [x]
       
  4665       = foldl (\<lambda>xs x. x # xs) (ys @ [x]) xs"
       
  4666     by (induct xs arbitrary: ys) auto
       
  4667   }
       
  4668   note aux = this
       
  4669   show ?case by (induct xs) (auto simp add: Cons aux)
       
  4670 qed
       
  4671 
       
  4672 lemmas in_set_code [code_unfold] = mem_iff [symmetric]
       
  4673 
       
  4674 lemma member_simps [simp, code]:
       
  4675   "member (x # xs) y \<longleftrightarrow> x = y \<or> member xs y"
       
  4676   "member [] y \<longleftrightarrow> False"
       
  4677   by (auto simp add: mem_iff)
       
  4678 
       
  4679 lemma member_set:
       
  4680   "member = set"
       
  4681   by (simp add: expand_fun_eq mem_iff mem_def)
       
  4682 
       
  4683 abbreviation (input) mem :: "'a \<Rightarrow> 'a list \<Rightarrow> bool" (infixl "mem" 55) where
       
  4684   "x mem xs \<equiv> member xs x" -- "for backward compatibility"
       
  4685 
       
  4686 lemma empty_null:
       
  4687   "xs = [] \<longleftrightarrow> null xs"
       
  4688 by (cases xs) simp_all
       
  4689 
       
  4690 lemma [code_unfold]:
       
  4691   "eq_class.eq xs [] \<longleftrightarrow> null xs"
       
  4692 by (simp add: eq empty_null)
       
  4693 
       
  4694 lemmas null_empty [code_post] =
       
  4695   empty_null [symmetric]
       
  4696 
       
  4697 lemma list_inter_conv:
       
  4698   "set (list_inter xs ys) = set xs \<inter> set ys"
       
  4699 by (induct xs) auto
       
  4700 
       
  4701 lemma list_all_iff [code_post]:
       
  4702   "list_all P xs \<longleftrightarrow> (\<forall>x \<in> set xs. P x)"
       
  4703 by (induct xs) auto
       
  4704 
       
  4705 lemmas list_ball_code [code_unfold] = list_all_iff [symmetric]
       
  4706 
       
  4707 lemma list_all_append [simp]:
       
  4708   "list_all P (xs @ ys) \<longleftrightarrow> (list_all P xs \<and> list_all P ys)"
       
  4709 by (induct xs) auto
       
  4710 
       
  4711 lemma list_all_rev [simp]:
       
  4712   "list_all P (rev xs) \<longleftrightarrow> list_all P xs"
       
  4713 by (simp add: list_all_iff)
       
  4714 
       
  4715 lemma list_all_length:
       
  4716   "list_all P xs \<longleftrightarrow> (\<forall>n < length xs. P (xs ! n))"
       
  4717 unfolding list_all_iff by (auto intro: all_nth_imp_all_set)
       
  4718 
       
  4719 lemma list_all_cong[fundef_cong]:
       
  4720   "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> f x = g x) \<Longrightarrow> list_all f xs = list_all g ys"
       
  4721 by (simp add: list_all_iff)
       
  4722 
       
  4723 lemma list_ex_iff [code_post]:
       
  4724   "list_ex P xs \<longleftrightarrow> (\<exists>x \<in> set xs. P x)"
       
  4725 by (induct xs) simp_all
       
  4726 
       
  4727 lemmas list_bex_code [code_unfold] =
       
  4728   list_ex_iff [symmetric]
       
  4729 
       
  4730 lemma list_ex_length:
       
  4731   "list_ex P xs \<longleftrightarrow> (\<exists>n < length xs. P (xs ! n))"
       
  4732 unfolding list_ex_iff set_conv_nth by auto
       
  4733 
       
  4734 lemma list_ex_cong[fundef_cong]:
       
  4735   "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> f x = g x) \<Longrightarrow> list_ex f xs = list_ex g ys"
       
  4736 by (simp add: list_ex_iff)
       
  4737 
       
  4738 lemma filtermap_conv:
       
  4739    "filtermap f xs = map (\<lambda>x. the (f x)) (filter (\<lambda>x. f x \<noteq> None) xs)"
       
  4740 by (induct xs) (simp_all split: option.split) 
       
  4741 
       
  4742 lemma map_filter_conv [simp]:
       
  4743   "map_filter f P xs = map f (filter P xs)"
       
  4744 by (induct xs) auto
       
  4745 
       
  4746 lemma length_remdups_length_unique [code_unfold]:
       
  4747   "length (remdups xs) = length_unique xs"
       
  4748 by (induct xs) simp_all
       
  4749 
       
  4750 lemma concat_map_code[code_unfold]:
       
  4751   "concat(map f xs) = concat_map f xs"
       
  4752 by (induct xs) simp_all
       
  4753 
       
  4754 declare INFI_def [code_unfold]
       
  4755 declare SUPR_def [code_unfold]
       
  4756 
       
  4757 declare set_map [symmetric, code_unfold]
       
  4758 
       
  4759 hide_const (open) length_unique
       
  4760 
       
  4761 
       
  4762 text {* Code for bounded quantification and summation over nats. *}
       
  4763 
       
  4764 lemma atMost_upto [code_unfold]:
       
  4765   "{..n} = set [0..<Suc n]"
       
  4766 by auto
       
  4767 
       
  4768 lemma atLeast_upt [code_unfold]:
       
  4769   "{..<n} = set [0..<n]"
       
  4770 by auto
       
  4771 
       
  4772 lemma greaterThanLessThan_upt [code_unfold]:
       
  4773   "{n<..<m} = set [Suc n..<m]"
       
  4774 by auto
       
  4775 
       
  4776 lemmas atLeastLessThan_upt [code_unfold] = set_upt [symmetric]
       
  4777 
       
  4778 lemma greaterThanAtMost_upt [code_unfold]:
       
  4779   "{n<..m} = set [Suc n..<Suc m]"
       
  4780 by auto
       
  4781 
       
  4782 lemma atLeastAtMost_upt [code_unfold]:
       
  4783   "{n..m} = set [n..<Suc m]"
       
  4784 by auto
       
  4785 
       
  4786 lemma all_nat_less_eq [code_unfold]:
       
  4787   "(\<forall>m<n\<Colon>nat. P m) \<longleftrightarrow> (\<forall>m \<in> {0..<n}. P m)"
       
  4788 by auto
       
  4789 
       
  4790 lemma ex_nat_less_eq [code_unfold]:
       
  4791   "(\<exists>m<n\<Colon>nat. P m) \<longleftrightarrow> (\<exists>m \<in> {0..<n}. P m)"
       
  4792 by auto
       
  4793 
       
  4794 lemma all_nat_less [code_unfold]:
       
  4795   "(\<forall>m\<le>n\<Colon>nat. P m) \<longleftrightarrow> (\<forall>m \<in> {0..n}. P m)"
       
  4796 by auto
       
  4797 
       
  4798 lemma ex_nat_less [code_unfold]:
       
  4799   "(\<exists>m\<le>n\<Colon>nat. P m) \<longleftrightarrow> (\<exists>m \<in> {0..n}. P m)"
       
  4800 by auto
       
  4801 
       
  4802 lemma setsum_set_distinct_conv_listsum:
       
  4803   "distinct xs \<Longrightarrow> setsum f (set xs) = listsum (map f xs)"
       
  4804 by (induct xs) simp_all
       
  4805 
       
  4806 lemma setsum_set_upt_conv_listsum [code_unfold]:
       
  4807   "setsum f (set [m..<n]) = listsum (map f [m..<n])"
       
  4808 by (rule setsum_set_distinct_conv_listsum) simp
       
  4809 
       
  4810 text {* General equivalence between @{const listsum} and @{const setsum} *}
       
  4811 lemma listsum_setsum_nth:
       
  4812   "listsum xs = (\<Sum> i = 0 ..< length xs. xs ! i)"
       
  4813 using setsum_set_upt_conv_listsum[of "op ! xs" 0 "length xs"]
       
  4814 by (simp add: map_nth)
       
  4815 
       
  4816 text {* Code for summation over ints. *}
       
  4817 
       
  4818 lemma greaterThanLessThan_upto [code_unfold]:
       
  4819   "{i<..<j::int} = set [i+1..j - 1]"
       
  4820 by auto
       
  4821 
       
  4822 lemma atLeastLessThan_upto [code_unfold]:
       
  4823   "{i..<j::int} = set [i..j - 1]"
       
  4824 by auto
       
  4825 
       
  4826 lemma greaterThanAtMost_upto [code_unfold]:
       
  4827   "{i<..j::int} = set [i+1..j]"
       
  4828 by auto
       
  4829 
       
  4830 lemmas atLeastAtMost_upto [code_unfold] = set_upto[symmetric]
       
  4831 
       
  4832 lemma setsum_set_upto_conv_listsum [code_unfold]:
       
  4833   "setsum f (set [i..j::int]) = listsum (map f [i..j])"
       
  4834 by (rule setsum_set_distinct_conv_listsum) simp
       
  4835 
       
  4836 
       
  4837 text {* Optimized code for @{text"\<forall>i\<in>{a..b::int}"} and @{text"\<forall>n:{a..<b::nat}"}
       
  4838 and similiarly for @{text"\<exists>"}. *}
       
  4839 
       
  4840 function all_from_to_nat :: "(nat \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where
       
  4841 "all_from_to_nat P i j =
       
  4842  (if i < j then if P i then all_from_to_nat P (i+1) j else False
       
  4843   else True)"
       
  4844 by auto
       
  4845 termination
       
  4846 by (relation "measure(%(P,i,j). j - i)") auto
       
  4847 
       
  4848 declare all_from_to_nat.simps[simp del]
       
  4849 
       
  4850 lemma all_from_to_nat_iff_ball:
       
  4851   "all_from_to_nat P i j = (ALL n : {i ..< j}. P n)"
       
  4852 proof(induct P i j rule:all_from_to_nat.induct)
       
  4853   case (1 P i j)
       
  4854   let ?yes = "i < j & P i"
       
  4855   show ?case
       
  4856   proof (cases)
       
  4857     assume ?yes
       
  4858     hence "all_from_to_nat P i j = (P i & all_from_to_nat P (i+1) j)"
       
  4859       by(simp add: all_from_to_nat.simps)
       
  4860     also have "... = (P i & (ALL n : {i+1 ..< j}. P n))" using `?yes` 1 by simp
       
  4861     also have "... = (ALL n : {i ..< j}. P n)" (is "?L = ?R")
       
  4862     proof
       
  4863       assume L: ?L
       
  4864       show ?R
       
  4865       proof clarify
       
  4866         fix n assume n: "n : {i..<j}"
       
  4867         show "P n"
       
  4868         proof cases
       
  4869           assume "n = i" thus "P n" using L by simp
       
  4870         next
       
  4871           assume "n ~= i"
       
  4872           hence "i+1 <= n" using n by auto
       
  4873           thus "P n" using L n by simp
       
  4874         qed
       
  4875       qed
       
  4876     next
       
  4877       assume R: ?R thus ?L using `?yes` 1 by auto
       
  4878     qed
       
  4879     finally show ?thesis .
       
  4880   next
       
  4881     assume "~?yes" thus ?thesis by(auto simp add: all_from_to_nat.simps)
       
  4882   qed
       
  4883 qed
       
  4884 
       
  4885 
       
  4886 lemma list_all_iff_all_from_to_nat[code_unfold]:
       
  4887   "list_all P [i..<j] = all_from_to_nat P i j"
       
  4888 by(simp add: all_from_to_nat_iff_ball list_all_iff)
       
  4889 
       
  4890 lemma list_ex_iff_not_all_from_to_not_nat[code_unfold]:
       
  4891   "list_ex P [i..<j] = (~all_from_to_nat (%x. ~P x) i j)"
       
  4892 by(simp add: all_from_to_nat_iff_ball list_ex_iff)
       
  4893 
       
  4894 
       
  4895 function all_from_to_int :: "(int \<Rightarrow> bool) \<Rightarrow> int \<Rightarrow> int \<Rightarrow> bool" where
       
  4896 "all_from_to_int P i j =
       
  4897  (if i <= j then if P i then all_from_to_int P (i+1) j else False
       
  4898   else True)"
       
  4899 by auto
       
  4900 termination
       
  4901 by (relation "measure(%(P,i,j). nat(j - i + 1))") auto
       
  4902 
       
  4903 declare all_from_to_int.simps[simp del]
       
  4904 
       
  4905 lemma all_from_to_int_iff_ball:
       
  4906   "all_from_to_int P i j = (ALL n : {i .. j}. P n)"
       
  4907 proof(induct P i j rule:all_from_to_int.induct)
       
  4908   case (1 P i j)
       
  4909   let ?yes = "i <= j & P i"
       
  4910   show ?case
       
  4911   proof (cases)
       
  4912     assume ?yes
       
  4913     hence "all_from_to_int P i j = (P i & all_from_to_int P (i+1) j)"
       
  4914       by(simp add: all_from_to_int.simps)
       
  4915     also have "... = (P i & (ALL n : {i+1 .. j}. P n))" using `?yes` 1 by simp
       
  4916     also have "... = (ALL n : {i .. j}. P n)" (is "?L = ?R")
       
  4917     proof
       
  4918       assume L: ?L
       
  4919       show ?R
       
  4920       proof clarify
       
  4921         fix n assume n: "n : {i..j}"
       
  4922         show "P n"
       
  4923         proof cases
       
  4924           assume "n = i" thus "P n" using L by simp
       
  4925         next
       
  4926           assume "n ~= i"
       
  4927           hence "i+1 <= n" using n by auto
       
  4928           thus "P n" using L n by simp
       
  4929         qed
       
  4930       qed
       
  4931     next
       
  4932       assume R: ?R thus ?L using `?yes` 1 by auto
       
  4933     qed
       
  4934     finally show ?thesis .
       
  4935   next
       
  4936     assume "~?yes" thus ?thesis by(auto simp add: all_from_to_int.simps)
       
  4937   qed
       
  4938 qed
       
  4939 
       
  4940 lemma list_all_iff_all_from_to_int[code_unfold]:
       
  4941   "list_all P [i..j] = all_from_to_int P i j"
       
  4942 by(simp add: all_from_to_int_iff_ball list_all_iff)
       
  4943 
       
  4944 lemma list_ex_iff_not_all_from_to_not_int[code_unfold]:
       
  4945   "list_ex P [i..j] = (~ all_from_to_int (%x. ~P x) i j)"
       
  4946 by(simp add: all_from_to_int_iff_ball list_ex_iff)
       
  4947 
       
  4948 
       
  4949 subsubsection {* Use convenient predefined operations *}
  4871 subsubsection {* Use convenient predefined operations *}
  4950 
  4872 
  4951 code_const "op @"
  4873 code_const "op @"
  4952   (SML infixr 7 "@")
  4874   (SML infixr 7 "@")
  4953   (OCaml infixr 6 "@")
  4875   (OCaml infixr 6 "@")
  4961   (Haskell "filter")
  4883   (Haskell "filter")
  4962 
  4884 
  4963 code_const concat
  4885 code_const concat
  4964   (Haskell "concat")
  4886   (Haskell "concat")
  4965 
  4887 
       
  4888 code_const List.maps
       
  4889   (Haskell "concatMap")
       
  4890 
  4966 code_const rev
  4891 code_const rev
  4967   (Haskell "reverse")
  4892   (Haskell "reverse")
  4968 
  4893 
  4969 code_const zip
  4894 code_const zip
  4970   (Haskell "zip")
  4895   (Haskell "zip")
  4971 
  4896 
       
  4897 code_const List.null
       
  4898   (Haskell "null")
       
  4899 
  4972 code_const takeWhile
  4900 code_const takeWhile
  4973   (Haskell "takeWhile")
  4901   (Haskell "takeWhile")
  4974 
  4902 
  4975 code_const dropWhile
  4903 code_const dropWhile
  4976   (Haskell "dropWhile")
  4904   (Haskell "dropWhile")
  4979   (Haskell "head")
  4907   (Haskell "head")
  4980 
  4908 
  4981 code_const last
  4909 code_const last
  4982   (Haskell "last")
  4910   (Haskell "last")
  4983 
  4911 
       
  4912 code_const list_all
       
  4913   (Haskell "all")
       
  4914 
       
  4915 code_const list_ex
       
  4916   (Haskell "any")
       
  4917 
  4984 end
  4918 end