6 section\<open>Lists in Zermelo-Fraenkel Set Theory\<close> |
6 section\<open>Lists in Zermelo-Fraenkel Set Theory\<close> |
7 |
7 |
8 theory List imports Datatype ArithSimp begin |
8 theory List imports Datatype ArithSimp begin |
9 |
9 |
10 consts |
10 consts |
11 list :: "i=>i" |
11 list :: "i\<Rightarrow>i" |
12 |
12 |
13 datatype |
13 datatype |
14 "list(A)" = Nil | Cons ("a \<in> A", "l \<in> list(A)") |
14 "list(A)" = Nil | Cons ("a \<in> A", "l \<in> list(A)") |
15 |
15 |
16 |
16 |
17 syntax |
17 syntax |
18 "_Nil" :: i (\<open>[]\<close>) |
18 "_Nil" :: i (\<open>[]\<close>) |
19 "_List" :: "is => i" (\<open>[(_)]\<close>) |
19 "_List" :: "is \<Rightarrow> i" (\<open>[(_)]\<close>) |
20 |
20 |
21 translations |
21 translations |
22 "[x, xs]" == "CONST Cons(x, [xs])" |
22 "[x, xs]" == "CONST Cons(x, [xs])" |
23 "[x]" == "CONST Cons(x, [])" |
23 "[x]" == "CONST Cons(x, [])" |
24 "[]" == "CONST Nil" |
24 "[]" == "CONST Nil" |
25 |
25 |
26 |
26 |
27 consts |
27 consts |
28 length :: "i=>i" |
28 length :: "i\<Rightarrow>i" |
29 hd :: "i=>i" |
29 hd :: "i\<Rightarrow>i" |
30 tl :: "i=>i" |
30 tl :: "i\<Rightarrow>i" |
31 |
31 |
32 primrec |
32 primrec |
33 "length([]) = 0" |
33 "length([]) = 0" |
34 "length(Cons(a,l)) = succ(length(l))" |
34 "length(Cons(a,l)) = succ(length(l))" |
35 |
35 |
41 "tl([]) = []" |
41 "tl([]) = []" |
42 "tl(Cons(a,l)) = l" |
42 "tl(Cons(a,l)) = l" |
43 |
43 |
44 |
44 |
45 consts |
45 consts |
46 map :: "[i=>i, i] => i" |
46 map :: "[i\<Rightarrow>i, i] \<Rightarrow> i" |
47 set_of_list :: "i=>i" |
47 set_of_list :: "i\<Rightarrow>i" |
48 app :: "[i,i]=>i" (infixr \<open>@\<close> 60) |
48 app :: "[i,i]\<Rightarrow>i" (infixr \<open>@\<close> 60) |
49 |
49 |
50 (*map is a binding operator -- it applies to meta-level functions, not |
50 (*map is a binding operator -- it applies to meta-level functions, not |
51 object-level functions. This simplifies the final form of term_rec_conv, |
51 object-level functions. This simplifies the final form of term_rec_conv, |
52 although complicating its derivation.*) |
52 although complicating its derivation.*) |
53 primrec |
53 primrec |
79 primrec |
79 primrec |
80 "list_add([]) = 0" |
80 "list_add([]) = 0" |
81 "list_add(Cons(a,l)) = a #+ list_add(l)" |
81 "list_add(Cons(a,l)) = a #+ list_add(l)" |
82 |
82 |
83 consts |
83 consts |
84 drop :: "[i,i]=>i" |
84 drop :: "[i,i]\<Rightarrow>i" |
85 |
85 |
86 primrec |
86 primrec |
87 drop_0: "drop(0,l) = l" |
87 drop_0: "drop(0,l) = l" |
88 drop_succ: "drop(succ(i), l) = tl (drop(i,l))" |
88 drop_succ: "drop(succ(i), l) = tl (drop(i,l))" |
89 |
89 |
90 |
90 |
91 (*** Thanks to Sidi Ehmety for the following ***) |
91 (*** Thanks to Sidi Ehmety for the following ***) |
92 |
92 |
93 definition |
93 definition |
94 (* Function `take' returns the first n elements of a list *) |
94 (* Function `take' returns the first n elements of a list *) |
95 take :: "[i,i]=>i" where |
95 take :: "[i,i]\<Rightarrow>i" where |
96 "take(n, as) \<equiv> list_rec(\<lambda>n\<in>nat. [], |
96 "take(n, as) \<equiv> list_rec(\<lambda>n\<in>nat. [], |
97 %a l r. \<lambda>n\<in>nat. nat_case([], %m. Cons(a, r`m), n), as)`n" |
97 \<lambda>a l r. \<lambda>n\<in>nat. nat_case([], \<lambda>m. Cons(a, r`m), n), as)`n" |
98 |
98 |
99 definition |
99 definition |
100 nth :: "[i, i]=>i" where |
100 nth :: "[i, i]\<Rightarrow>i" where |
101 \<comment> \<open>returns the (n+1)th element of a list, or 0 if the |
101 \<comment> \<open>returns the (n+1)th element of a list, or 0 if the |
102 list is too short.\<close> |
102 list is too short.\<close> |
103 "nth(n, as) \<equiv> list_rec(\<lambda>n\<in>nat. 0, |
103 "nth(n, as) \<equiv> list_rec(\<lambda>n\<in>nat. 0, |
104 %a l r. \<lambda>n\<in>nat. nat_case(a, %m. r`m, n), as) ` n" |
104 \<lambda>a l r. \<lambda>n\<in>nat. nat_case(a, \<lambda>m. r`m, n), as) ` n" |
105 |
105 |
106 definition |
106 definition |
107 list_update :: "[i, i, i]=>i" where |
107 list_update :: "[i, i, i]\<Rightarrow>i" where |
108 "list_update(xs, i, v) \<equiv> list_rec(\<lambda>n\<in>nat. Nil, |
108 "list_update(xs, i, v) \<equiv> list_rec(\<lambda>n\<in>nat. Nil, |
109 %u us vs. \<lambda>n\<in>nat. nat_case(Cons(v, us), %m. Cons(u, vs`m), n), xs)`i" |
109 \<lambda>u us vs. \<lambda>n\<in>nat. nat_case(Cons(v, us), \<lambda>m. Cons(u, vs`m), n), xs)`i" |
110 |
110 |
111 consts |
111 consts |
112 filter :: "[i=>o, i] => i" |
112 filter :: "[i\<Rightarrow>o, i] \<Rightarrow> i" |
113 upt :: "[i, i] =>i" |
113 upt :: "[i, i] \<Rightarrow>i" |
114 |
114 |
115 primrec |
115 primrec |
116 "filter(P, Nil) = Nil" |
116 "filter(P, Nil) = Nil" |
117 "filter(P, Cons(x, xs)) = |
117 "filter(P, Cons(x, xs)) = |
118 (if P(x) then Cons(x, filter(P, xs)) else filter(P, xs))" |
118 (if P(x) then Cons(x, filter(P, xs)) else filter(P, xs))" |
120 primrec |
120 primrec |
121 "upt(i, 0) = Nil" |
121 "upt(i, 0) = Nil" |
122 "upt(i, succ(j)) = (if i \<le> j then upt(i, j)@[j] else Nil)" |
122 "upt(i, succ(j)) = (if i \<le> j then upt(i, j)@[j] else Nil)" |
123 |
123 |
124 definition |
124 definition |
125 min :: "[i,i] =>i" where |
125 min :: "[i,i] \<Rightarrow>i" where |
126 "min(x, y) \<equiv> (if x \<le> y then x else y)" |
126 "min(x, y) \<equiv> (if x \<le> y then x else y)" |
127 |
127 |
128 definition |
128 definition |
129 max :: "[i, i] =>i" where |
129 max :: "[i, i] \<Rightarrow>i" where |
130 "max(x, y) \<equiv> (if x \<le> y then y else x)" |
130 "max(x, y) \<equiv> (if x \<le> y then y else x)" |
131 |
131 |
132 (*** Aspects of the datatype definition ***) |
132 (*** Aspects of the datatype definition ***) |
133 |
133 |
134 declare list.intros [simp,TC] |
134 declare list.intros [simp,TC] |
284 by (simp add: list_add_list_def) |
284 by (simp add: list_add_list_def) |
285 |
285 |
286 |
286 |
287 (*** theorems about map ***) |
287 (*** theorems about map ***) |
288 |
288 |
289 lemma map_ident [simp]: "l \<in> list(A) \<Longrightarrow> map(%u. u, l) = l" |
289 lemma map_ident [simp]: "l \<in> list(A) \<Longrightarrow> map(\<lambda>u. u, l) = l" |
290 apply (induct_tac "l") |
290 apply (induct_tac "l") |
291 apply (simp_all (no_asm_simp)) |
291 apply (simp_all (no_asm_simp)) |
292 done |
292 done |
293 |
293 |
294 lemma map_compose: "l \<in> list(A) \<Longrightarrow> map(h, map(j,l)) = map(%u. h(j(u)), l)" |
294 lemma map_compose: "l \<in> list(A) \<Longrightarrow> map(h, map(j,l)) = map(\<lambda>u. h(j(u)), l)" |
295 apply (induct_tac "l") |
295 apply (induct_tac "l") |
296 apply (simp_all (no_asm_simp)) |
296 apply (simp_all (no_asm_simp)) |
297 done |
297 done |
298 |
298 |
299 lemma map_app_distrib: "xs: list(A) \<Longrightarrow> map(h, xs@ys) = map(h,xs) @ map(h,ys)" |
299 lemma map_app_distrib: "xs: list(A) \<Longrightarrow> map(h, xs@ys) = map(h,xs) @ map(h,ys)" |
307 done |
307 done |
308 |
308 |
309 lemma list_rec_map: |
309 lemma list_rec_map: |
310 "l \<in> list(A) \<Longrightarrow> |
310 "l \<in> list(A) \<Longrightarrow> |
311 list_rec(c, d, map(h,l)) = |
311 list_rec(c, d, map(h,l)) = |
312 list_rec(c, %x xs r. d(h(x), map(h,xs), r), l)" |
312 list_rec(c, \<lambda>x xs r. d(h(x), map(h,xs), r), l)" |
313 apply (induct_tac "l") |
313 apply (induct_tac "l") |
314 apply (simp_all (no_asm_simp)) |
314 apply (simp_all (no_asm_simp)) |
315 done |
315 done |
316 |
316 |
317 (** theorems about list(Collect(A,P)) -- used in Induct/Term.thy **) |
317 (** theorems about list(Collect(A,P)) -- used in Induct/Term.thy **) |
508 done |
508 done |
509 |
509 |
510 lemma filter_is_subset: "xs:list(A) \<Longrightarrow> set_of_list(filter(P,xs)) \<subseteq> set_of_list(xs)" |
510 lemma filter_is_subset: "xs:list(A) \<Longrightarrow> set_of_list(filter(P,xs)) \<subseteq> set_of_list(xs)" |
511 by (induct_tac "xs", auto) |
511 by (induct_tac "xs", auto) |
512 |
512 |
513 lemma filter_False [simp]: "xs:list(A) \<Longrightarrow> filter(%p. False, xs) = Nil" |
513 lemma filter_False [simp]: "xs:list(A) \<Longrightarrow> filter(\<lambda>p. False, xs) = Nil" |
514 by (induct_tac "xs", auto) |
514 by (induct_tac "xs", auto) |
515 |
515 |
516 lemma filter_True [simp]: "xs:list(A) \<Longrightarrow> filter(%p. True, xs) = xs" |
516 lemma filter_True [simp]: "xs:list(A) \<Longrightarrow> filter(\<lambda>p. True, xs) = xs" |
517 by (induct_tac "xs", auto) |
517 by (induct_tac "xs", auto) |
518 |
518 |
519 (** length **) |
519 (** length **) |
520 |
520 |
521 lemma length_is_0_iff [simp]: "xs:list(A) \<Longrightarrow> length(xs)=0 \<longleftrightarrow> xs=Nil" |
521 lemma length_is_0_iff [simp]: "xs:list(A) \<Longrightarrow> length(xs)=0 \<longleftrightarrow> xs=Nil" |
851 subsection\<open>The function zip\<close> |
851 subsection\<open>The function zip\<close> |
852 |
852 |
853 text\<open>Crafty definition to eliminate a type argument\<close> |
853 text\<open>Crafty definition to eliminate a type argument\<close> |
854 |
854 |
855 consts |
855 consts |
856 zip_aux :: "[i,i]=>i" |
856 zip_aux :: "[i,i]\<Rightarrow>i" |
857 |
857 |
858 primrec (*explicit lambda is required because both arguments of "un" vary*) |
858 primrec (*explicit lambda is required because both arguments of "un" vary*) |
859 "zip_aux(B,[]) = |
859 "zip_aux(B,[]) = |
860 (\<lambda>ys \<in> list(B). list_case([], %y l. [], ys))" |
860 (\<lambda>ys \<in> list(B). list_case([], \<lambda>y l. [], ys))" |
861 |
861 |
862 "zip_aux(B,Cons(x,l)) = |
862 "zip_aux(B,Cons(x,l)) = |
863 (\<lambda>ys \<in> list(B). |
863 (\<lambda>ys \<in> list(B). |
864 list_case(Nil, %y zs. Cons(<x,y>, zip_aux(B,l)`zs), ys))" |
864 list_case(Nil, \<lambda>y zs. Cons(\<langle>x,y\<rangle>, zip_aux(B,l)`zs), ys))" |
865 |
865 |
866 definition |
866 definition |
867 zip :: "[i, i]=>i" where |
867 zip :: "[i, i]\<Rightarrow>i" where |
868 "zip(xs, ys) \<equiv> zip_aux(set_of_list(ys),xs)`ys" |
868 "zip(xs, ys) \<equiv> zip_aux(set_of_list(ys),xs)`ys" |
869 |
869 |
870 |
870 |
871 (* zip equations *) |
871 (* zip equations *) |
872 |
872 |
895 apply (blast intro: list_mono [THEN subsetD]) |
895 apply (blast intro: list_mono [THEN subsetD]) |
896 done |
896 done |
897 |
897 |
898 lemma zip_Cons_Cons [simp]: |
898 lemma zip_Cons_Cons [simp]: |
899 "\<lbrakk>xs:list(A); ys:list(B); x \<in> A; y \<in> B\<rbrakk> \<Longrightarrow> |
899 "\<lbrakk>xs:list(A); ys:list(B); x \<in> A; y \<in> B\<rbrakk> \<Longrightarrow> |
900 zip(Cons(x,xs), Cons(y, ys)) = Cons(<x,y>, zip(xs, ys))" |
900 zip(Cons(x,xs), Cons(y, ys)) = Cons(\<langle>x,y\<rangle>, zip(xs, ys))" |
901 apply (simp add: zip_def, auto) |
901 apply (simp add: zip_def, auto) |
902 apply (rule zip_aux_unique, auto) |
902 apply (rule zip_aux_unique, auto) |
903 apply (simp add: list_on_set_of_list [of _ B]) |
903 apply (simp add: list_on_set_of_list [of _ B]) |
904 apply (blast intro: list_on_set_of_list list_mono [THEN subsetD]) |
904 apply (blast intro: list_on_set_of_list list_mono [THEN subsetD]) |
905 done |
905 done |
965 declare nth_zip [simp] |
965 declare nth_zip [simp] |
966 |
966 |
967 lemma set_of_list_zip [rule_format]: |
967 lemma set_of_list_zip [rule_format]: |
968 "\<lbrakk>xs:list(A); ys:list(B); i \<in> nat\<rbrakk> |
968 "\<lbrakk>xs:list(A); ys:list(B); i \<in> nat\<rbrakk> |
969 \<Longrightarrow> set_of_list(zip(xs, ys)) = |
969 \<Longrightarrow> set_of_list(zip(xs, ys)) = |
970 {<x, y>:A*B. \<exists>i\<in>nat. i < min(length(xs), length(ys)) |
970 {\<langle>x, y\<rangle>:A*B. \<exists>i\<in>nat. i < min(length(xs), length(ys)) |
971 \<and> x = nth(i, xs) \<and> y = nth(i, ys)}" |
971 \<and> x = nth(i, xs) \<and> y = nth(i, ys)}" |
972 by (force intro!: Collect_cong simp add: lt_min_iff set_of_list_conv_nth) |
972 by (force intro!: Collect_cong simp add: lt_min_iff set_of_list_conv_nth) |
973 |
973 |
974 (** list_update **) |
974 (** list_update **) |
975 |
975 |
1177 done |
1177 done |
1178 |
1178 |
1179 (** sublist (a generalization of nth to sets) **) |
1179 (** sublist (a generalization of nth to sets) **) |
1180 |
1180 |
1181 definition |
1181 definition |
1182 sublist :: "[i, i] => i" where |
1182 sublist :: "[i, i] \<Rightarrow> i" where |
1183 "sublist(xs, A)\<equiv> |
1183 "sublist(xs, A)\<equiv> |
1184 map(fst, (filter(%p. snd(p): A, zip(xs, upt(0,length(xs))))))" |
1184 map(fst, (filter(\<lambda>p. snd(p): A, zip(xs, upt(0,length(xs))))))" |
1185 |
1185 |
1186 lemma sublist_0 [simp]: "xs:list(A) \<Longrightarrow>sublist(xs, 0) =Nil" |
1186 lemma sublist_0 [simp]: "xs:list(A) \<Longrightarrow>sublist(xs, 0) =Nil" |
1187 by (unfold sublist_def, auto) |
1187 by (unfold sublist_def, auto) |
1188 |
1188 |
1189 lemma sublist_Nil [simp]: "sublist(Nil, A) = Nil" |
1189 lemma sublist_Nil [simp]: "sublist(Nil, A) = Nil" |
1190 by (unfold sublist_def, auto) |
1190 by (unfold sublist_def, auto) |
1191 |
1191 |
1192 lemma sublist_shift_lemma: |
1192 lemma sublist_shift_lemma: |
1193 "\<lbrakk>xs:list(B); i \<in> nat\<rbrakk> \<Longrightarrow> |
1193 "\<lbrakk>xs:list(B); i \<in> nat\<rbrakk> \<Longrightarrow> |
1194 map(fst, filter(%p. snd(p):A, zip(xs, upt(i,i #+ length(xs))))) = |
1194 map(fst, filter(\<lambda>p. snd(p):A, zip(xs, upt(i,i #+ length(xs))))) = |
1195 map(fst, filter(%p. snd(p):nat \<and> snd(p) #+ i \<in> A, zip(xs,upt(0,length(xs)))))" |
1195 map(fst, filter(\<lambda>p. snd(p):nat \<and> snd(p) #+ i \<in> A, zip(xs,upt(0,length(xs)))))" |
1196 apply (erule list_append_induct) |
1196 apply (erule list_append_induct) |
1197 apply (simp (no_asm_simp)) |
1197 apply (simp (no_asm_simp)) |
1198 apply (auto simp add: add_commute length_app filter_append map_app_distrib) |
1198 apply (auto simp add: add_commute length_app filter_append map_app_distrib) |
1199 done |
1199 done |
1200 |
1200 |