src/ZF/List_ZF.thy
author wenzelm
Thu Sep 02 00:48:07 2010 +0200 (2010-09-02)
changeset 38980 af73cf0dc31f
parent 35425 d4e747d3a874
child 45602 2a858377c3d2
permissions -rw-r--r--
turned show_question_marks into proper configuration option;
show_question_marks only affects regular type/term pretty printing, not raw Term.string_of_vname;
tuned;
wenzelm@32960
     1
(*  Title:      ZF/List_ZF.thy
krauss@26056
     2
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
krauss@26056
     3
    Copyright   1994  University of Cambridge
krauss@26056
     4
*)
krauss@26056
     5
krauss@26056
     6
header{*Lists in Zermelo-Fraenkel Set Theory*}
krauss@26056
     7
krauss@26056
     8
theory List_ZF imports Datatype_ZF ArithSimp begin
krauss@26056
     9
krauss@26056
    10
consts
krauss@26056
    11
  list       :: "i=>i"
krauss@26056
    12
krauss@26056
    13
datatype
krauss@26056
    14
  "list(A)" = Nil | Cons ("a:A", "l: list(A)")
krauss@26056
    15
krauss@26056
    16
krauss@26056
    17
syntax
wenzelm@35425
    18
 "_Nil" :: i  ("[]")
wenzelm@35425
    19
 "_List" :: "is => i"  ("[(_)]")
krauss@26056
    20
krauss@26056
    21
translations
wenzelm@35068
    22
  "[x, xs]"     == "CONST Cons(x, [xs])"
wenzelm@35068
    23
  "[x]"         == "CONST Cons(x, [])"
wenzelm@35068
    24
  "[]"          == "CONST Nil"
krauss@26056
    25
krauss@26056
    26
krauss@26056
    27
consts
krauss@26056
    28
  length :: "i=>i"
krauss@26056
    29
  hd     :: "i=>i"
krauss@26056
    30
  tl     :: "i=>i"
krauss@26056
    31
krauss@26056
    32
primrec
krauss@26056
    33
  "length([]) = 0"
krauss@26056
    34
  "length(Cons(a,l)) = succ(length(l))"
krauss@26056
    35
krauss@26056
    36
primrec
krauss@26056
    37
  "hd([]) = 0"
krauss@26056
    38
  "hd(Cons(a,l)) = a"
krauss@26056
    39
krauss@26056
    40
primrec
krauss@26056
    41
  "tl([]) = []"
krauss@26056
    42
  "tl(Cons(a,l)) = l"
krauss@26056
    43
krauss@26056
    44
krauss@26056
    45
consts
krauss@26056
    46
  map         :: "[i=>i, i] => i"
krauss@26056
    47
  set_of_list :: "i=>i"
krauss@26056
    48
  app         :: "[i,i]=>i"                        (infixr "@" 60)
krauss@26056
    49
krauss@26056
    50
(*map is a binding operator -- it applies to meta-level functions, not
krauss@26056
    51
object-level functions.  This simplifies the final form of term_rec_conv,
krauss@26056
    52
although complicating its derivation.*)
krauss@26056
    53
primrec
krauss@26056
    54
  "map(f,[]) = []"
krauss@26056
    55
  "map(f,Cons(a,l)) = Cons(f(a), map(f,l))"
krauss@26056
    56
krauss@26056
    57
primrec
krauss@26056
    58
  "set_of_list([]) = 0"
krauss@26056
    59
  "set_of_list(Cons(a,l)) = cons(a, set_of_list(l))"
krauss@26056
    60
krauss@26056
    61
primrec
krauss@26056
    62
  app_Nil:  "[] @ ys = ys"
krauss@26056
    63
  app_Cons: "(Cons(a,l)) @ ys = Cons(a, l @ ys)"
krauss@26056
    64
krauss@26056
    65
krauss@26056
    66
consts
krauss@26056
    67
  rev :: "i=>i"
krauss@26056
    68
  flat       :: "i=>i"
krauss@26056
    69
  list_add   :: "i=>i"
krauss@26056
    70
krauss@26056
    71
primrec
krauss@26056
    72
  "rev([]) = []"
krauss@26056
    73
  "rev(Cons(a,l)) = rev(l) @ [a]"
krauss@26056
    74
krauss@26056
    75
primrec
krauss@26056
    76
  "flat([]) = []"
krauss@26056
    77
  "flat(Cons(l,ls)) = l @ flat(ls)"
krauss@26056
    78
krauss@26056
    79
primrec
krauss@26056
    80
  "list_add([]) = 0"
krauss@26056
    81
  "list_add(Cons(a,l)) = a #+ list_add(l)"
krauss@26056
    82
krauss@26056
    83
consts
krauss@26056
    84
  drop       :: "[i,i]=>i"
krauss@26056
    85
krauss@26056
    86
primrec
krauss@26056
    87
  drop_0:    "drop(0,l) = l"
krauss@26056
    88
  drop_succ: "drop(succ(i), l) = tl (drop(i,l))"
krauss@26056
    89
krauss@26056
    90
krauss@26056
    91
(*** Thanks to Sidi Ehmety for the following ***)
krauss@26056
    92
krauss@26056
    93
definition
krauss@26056
    94
(* Function `take' returns the first n elements of a list *)
krauss@26056
    95
  take     :: "[i,i]=>i"  where
krauss@26056
    96
  "take(n, as) == list_rec(lam n:nat. [],
wenzelm@32960
    97
                %a l r. lam n:nat. nat_case([], %m. Cons(a, r`m), n), as)`n"
krauss@26056
    98
krauss@26056
    99
definition
krauss@26056
   100
  nth :: "[i, i]=>i"  where
krauss@26056
   101
  --{*returns the (n+1)th element of a list, or 0 if the
krauss@26056
   102
   list is too short.*}
krauss@26056
   103
  "nth(n, as) == list_rec(lam n:nat. 0,
wenzelm@32960
   104
                          %a l r. lam n:nat. nat_case(a, %m. r`m, n), as) ` n"
krauss@26056
   105
krauss@26056
   106
definition
krauss@26056
   107
  list_update :: "[i, i, i]=>i"  where
krauss@26056
   108
  "list_update(xs, i, v) == list_rec(lam n:nat. Nil,
krauss@26056
   109
      %u us vs. lam n:nat. nat_case(Cons(v, us), %m. Cons(u, vs`m), n), xs)`i"
krauss@26056
   110
krauss@26056
   111
consts
krauss@26056
   112
  filter :: "[i=>o, i] => i"
krauss@26056
   113
  upt :: "[i, i] =>i"
krauss@26056
   114
krauss@26056
   115
primrec
krauss@26056
   116
  "filter(P, Nil) = Nil"
krauss@26056
   117
  "filter(P, Cons(x, xs)) =
krauss@26056
   118
     (if P(x) then Cons(x, filter(P, xs)) else filter(P, xs))"
krauss@26056
   119
krauss@26056
   120
primrec
krauss@26056
   121
  "upt(i, 0) = Nil"
krauss@26056
   122
  "upt(i, succ(j)) = (if i le j then upt(i, j)@[j] else Nil)"
krauss@26056
   123
krauss@26056
   124
definition
krauss@26056
   125
  min :: "[i,i] =>i"  where
krauss@26056
   126
    "min(x, y) == (if x le y then x else y)"
krauss@26056
   127
krauss@26056
   128
definition
krauss@26056
   129
  max :: "[i, i] =>i"  where
krauss@26056
   130
    "max(x, y) == (if x le y then y else x)"
krauss@26056
   131
krauss@26056
   132
(*** Aspects of the datatype definition ***)
krauss@26056
   133
krauss@26056
   134
declare list.intros [simp,TC]
krauss@26056
   135
krauss@26056
   136
(*An elimination rule, for type-checking*)
krauss@26056
   137
inductive_cases ConsE: "Cons(a,l) : list(A)"
krauss@26056
   138
krauss@26056
   139
lemma Cons_type_iff [simp]: "Cons(a,l) \<in> list(A) <-> a \<in> A & l \<in> list(A)"
krauss@26056
   140
by (blast elim: ConsE) 
krauss@26056
   141
krauss@26056
   142
(*Proving freeness results*)
krauss@26056
   143
lemma Cons_iff: "Cons(a,l)=Cons(a',l') <-> a=a' & l=l'"
krauss@26056
   144
by auto
krauss@26056
   145
krauss@26056
   146
lemma Nil_Cons_iff: "~ Nil=Cons(a,l)"
krauss@26056
   147
by auto
krauss@26056
   148
krauss@26056
   149
lemma list_unfold: "list(A) = {0} + (A * list(A))"
krauss@26056
   150
by (blast intro!: list.intros [unfolded list.con_defs]
krauss@26056
   151
          elim: list.cases [unfolded list.con_defs])
krauss@26056
   152
krauss@26056
   153
krauss@26056
   154
(**  Lemmas to justify using "list" in other recursive type definitions **)
krauss@26056
   155
krauss@26056
   156
lemma list_mono: "A<=B ==> list(A) <= list(B)"
krauss@26056
   157
apply (unfold list.defs )
krauss@26056
   158
apply (rule lfp_mono)
krauss@26056
   159
apply (simp_all add: list.bnd_mono)
krauss@26056
   160
apply (assumption | rule univ_mono basic_monos)+
krauss@26056
   161
done
krauss@26056
   162
krauss@26056
   163
(*There is a similar proof by list induction.*)
krauss@26056
   164
lemma list_univ: "list(univ(A)) <= univ(A)"
krauss@26056
   165
apply (unfold list.defs list.con_defs)
krauss@26056
   166
apply (rule lfp_lowerbound)
krauss@26056
   167
apply (rule_tac [2] A_subset_univ [THEN univ_mono])
krauss@26056
   168
apply (blast intro!: zero_in_univ Inl_in_univ Inr_in_univ Pair_in_univ)
krauss@26056
   169
done
krauss@26056
   170
krauss@26056
   171
(*These two theorems justify datatypes involving list(nat), list(A), ...*)
krauss@26056
   172
lemmas list_subset_univ = subset_trans [OF list_mono list_univ]
krauss@26056
   173
krauss@26056
   174
lemma list_into_univ: "[| l: list(A);  A <= univ(B) |] ==> l: univ(B)"
krauss@26056
   175
by (blast intro: list_subset_univ [THEN subsetD])
krauss@26056
   176
krauss@26056
   177
lemma list_case_type:
krauss@26056
   178
    "[| l: list(A);
krauss@26056
   179
        c: C(Nil);
krauss@26056
   180
        !!x y. [| x: A;  y: list(A) |] ==> h(x,y): C(Cons(x,y))
krauss@26056
   181
     |] ==> list_case(c,h,l) : C(l)"
krauss@26056
   182
by (erule list.induct, auto)
krauss@26056
   183
krauss@26056
   184
lemma list_0_triv: "list(0) = {Nil}"
krauss@26056
   185
apply (rule equalityI, auto) 
krauss@26056
   186
apply (induct_tac x, auto) 
krauss@26056
   187
done
krauss@26056
   188
krauss@26056
   189
krauss@26056
   190
(*** List functions ***)
krauss@26056
   191
krauss@26056
   192
lemma tl_type: "l: list(A) ==> tl(l) : list(A)"
krauss@26056
   193
apply (induct_tac "l")
krauss@26056
   194
apply (simp_all (no_asm_simp) add: list.intros)
krauss@26056
   195
done
krauss@26056
   196
krauss@26056
   197
(** drop **)
krauss@26056
   198
krauss@26056
   199
lemma drop_Nil [simp]: "i:nat ==> drop(i, Nil) = Nil"
krauss@26056
   200
apply (induct_tac "i")
krauss@26056
   201
apply (simp_all (no_asm_simp))
krauss@26056
   202
done
krauss@26056
   203
krauss@26056
   204
lemma drop_succ_Cons [simp]: "i:nat ==> drop(succ(i), Cons(a,l)) = drop(i,l)"
krauss@26056
   205
apply (rule sym)
krauss@26056
   206
apply (induct_tac "i")
krauss@26056
   207
apply (simp (no_asm))
krauss@26056
   208
apply (simp (no_asm_simp))
krauss@26056
   209
done
krauss@26056
   210
krauss@26056
   211
lemma drop_type [simp,TC]: "[| i:nat; l: list(A) |] ==> drop(i,l) : list(A)"
krauss@26056
   212
apply (induct_tac "i")
krauss@26056
   213
apply (simp_all (no_asm_simp) add: tl_type)
krauss@26056
   214
done
krauss@26056
   215
krauss@26056
   216
declare drop_succ [simp del]
krauss@26056
   217
krauss@26056
   218
krauss@26056
   219
(** Type checking -- proved by induction, as usual **)
krauss@26056
   220
krauss@26056
   221
lemma list_rec_type [TC]:
krauss@26056
   222
    "[| l: list(A);
krauss@26056
   223
        c: C(Nil);
krauss@26056
   224
        !!x y r. [| x:A;  y: list(A);  r: C(y) |] ==> h(x,y,r): C(Cons(x,y))
krauss@26056
   225
     |] ==> list_rec(c,h,l) : C(l)"
krauss@26056
   226
by (induct_tac "l", auto)
krauss@26056
   227
krauss@26056
   228
(** map **)
krauss@26056
   229
krauss@26056
   230
lemma map_type [TC]:
krauss@26056
   231
    "[| l: list(A);  !!x. x: A ==> h(x): B |] ==> map(h,l) : list(B)"
krauss@26056
   232
apply (simp add: map_list_def)
krauss@26056
   233
apply (typecheck add: list.intros list_rec_type, blast)
krauss@26056
   234
done
krauss@26056
   235
krauss@26056
   236
lemma map_type2 [TC]: "l: list(A) ==> map(h,l) : list({h(u). u:A})"
krauss@26056
   237
apply (erule map_type)
krauss@26056
   238
apply (erule RepFunI)
krauss@26056
   239
done
krauss@26056
   240
krauss@26056
   241
(** length **)
krauss@26056
   242
krauss@26056
   243
lemma length_type [TC]: "l: list(A) ==> length(l) : nat"
krauss@26056
   244
by (simp add: length_list_def)
krauss@26056
   245
krauss@26056
   246
lemma lt_length_in_nat:
krauss@26056
   247
   "[|x < length(xs); xs \<in> list(A)|] ==> x \<in> nat"
krauss@26056
   248
by (frule lt_nat_in_nat, typecheck) 
krauss@26056
   249
krauss@26056
   250
(** app **)
krauss@26056
   251
krauss@26056
   252
lemma app_type [TC]: "[| xs: list(A);  ys: list(A) |] ==> xs@ys : list(A)"
krauss@26056
   253
by (simp add: app_list_def)
krauss@26056
   254
krauss@26056
   255
(** rev **)
krauss@26056
   256
krauss@26056
   257
lemma rev_type [TC]: "xs: list(A) ==> rev(xs) : list(A)"
krauss@26056
   258
by (simp add: rev_list_def)
krauss@26056
   259
krauss@26056
   260
krauss@26056
   261
(** flat **)
krauss@26056
   262
krauss@26056
   263
lemma flat_type [TC]: "ls: list(list(A)) ==> flat(ls) : list(A)"
krauss@26056
   264
by (simp add: flat_list_def)
krauss@26056
   265
krauss@26056
   266
krauss@26056
   267
(** set_of_list **)
krauss@26056
   268
krauss@26056
   269
lemma set_of_list_type [TC]: "l: list(A) ==> set_of_list(l) : Pow(A)"
krauss@26056
   270
apply (unfold set_of_list_list_def)
krauss@26056
   271
apply (erule list_rec_type, auto)
krauss@26056
   272
done
krauss@26056
   273
krauss@26056
   274
lemma set_of_list_append:
krauss@26056
   275
     "xs: list(A) ==> set_of_list (xs@ys) = set_of_list(xs) Un set_of_list(ys)"
krauss@26056
   276
apply (erule list.induct)
krauss@26056
   277
apply (simp_all (no_asm_simp) add: Un_cons)
krauss@26056
   278
done
krauss@26056
   279
krauss@26056
   280
krauss@26056
   281
(** list_add **)
krauss@26056
   282
krauss@26056
   283
lemma list_add_type [TC]: "xs: list(nat) ==> list_add(xs) : nat"
krauss@26056
   284
by (simp add: list_add_list_def)
krauss@26056
   285
krauss@26056
   286
krauss@26056
   287
(*** theorems about map ***)
krauss@26056
   288
krauss@26056
   289
lemma map_ident [simp]: "l: list(A) ==> map(%u. u, l) = l"
krauss@26056
   290
apply (induct_tac "l")
krauss@26056
   291
apply (simp_all (no_asm_simp))
krauss@26056
   292
done
krauss@26056
   293
krauss@26056
   294
lemma map_compose: "l: list(A) ==> map(h, map(j,l)) = map(%u. h(j(u)), l)"
krauss@26056
   295
apply (induct_tac "l")
krauss@26056
   296
apply (simp_all (no_asm_simp))
krauss@26056
   297
done
krauss@26056
   298
krauss@26056
   299
lemma map_app_distrib: "xs: list(A) ==> map(h, xs@ys) = map(h,xs) @ map(h,ys)"
krauss@26056
   300
apply (induct_tac "xs")
krauss@26056
   301
apply (simp_all (no_asm_simp))
krauss@26056
   302
done
krauss@26056
   303
krauss@26056
   304
lemma map_flat: "ls: list(list(A)) ==> map(h, flat(ls)) = flat(map(map(h),ls))"
krauss@26056
   305
apply (induct_tac "ls")
krauss@26056
   306
apply (simp_all (no_asm_simp) add: map_app_distrib)
krauss@26056
   307
done
krauss@26056
   308
krauss@26056
   309
lemma list_rec_map:
krauss@26056
   310
     "l: list(A) ==>
krauss@26056
   311
      list_rec(c, d, map(h,l)) =
krauss@26056
   312
      list_rec(c, %x xs r. d(h(x), map(h,xs), r), l)"
krauss@26056
   313
apply (induct_tac "l")
krauss@26056
   314
apply (simp_all (no_asm_simp))
krauss@26056
   315
done
krauss@26056
   316
krauss@26056
   317
(** theorems about list(Collect(A,P)) -- used in Induct/Term.thy **)
krauss@26056
   318
krauss@26056
   319
(* c : list(Collect(B,P)) ==> c : list(B) *)
krauss@26056
   320
lemmas list_CollectD = Collect_subset [THEN list_mono, THEN subsetD, standard]
krauss@26056
   321
krauss@26056
   322
lemma map_list_Collect: "l: list({x:A. h(x)=j(x)}) ==> map(h,l) = map(j,l)"
krauss@26056
   323
apply (induct_tac "l")
krauss@26056
   324
apply (simp_all (no_asm_simp))
krauss@26056
   325
done
krauss@26056
   326
krauss@26056
   327
(*** theorems about length ***)
krauss@26056
   328
krauss@26056
   329
lemma length_map [simp]: "xs: list(A) ==> length(map(h,xs)) = length(xs)"
krauss@26056
   330
by (induct_tac "xs", simp_all)
krauss@26056
   331
krauss@26056
   332
lemma length_app [simp]:
krauss@26056
   333
     "[| xs: list(A); ys: list(A) |]
krauss@26056
   334
      ==> length(xs@ys) = length(xs) #+ length(ys)"
krauss@26056
   335
by (induct_tac "xs", simp_all)
krauss@26056
   336
krauss@26056
   337
lemma length_rev [simp]: "xs: list(A) ==> length(rev(xs)) = length(xs)"
krauss@26056
   338
apply (induct_tac "xs")
krauss@26056
   339
apply (simp_all (no_asm_simp) add: length_app)
krauss@26056
   340
done
krauss@26056
   341
krauss@26056
   342
lemma length_flat:
krauss@26056
   343
     "ls: list(list(A)) ==> length(flat(ls)) = list_add(map(length,ls))"
krauss@26056
   344
apply (induct_tac "ls")
krauss@26056
   345
apply (simp_all (no_asm_simp) add: length_app)
krauss@26056
   346
done
krauss@26056
   347
krauss@26056
   348
(** Length and drop **)
krauss@26056
   349
krauss@26056
   350
(*Lemma for the inductive step of drop_length*)
krauss@26056
   351
lemma drop_length_Cons [rule_format]:
krauss@26056
   352
     "xs: list(A) ==>
krauss@26056
   353
           \<forall>x.  EX z zs. drop(length(xs), Cons(x,xs)) = Cons(z,zs)"
krauss@26056
   354
by (erule list.induct, simp_all)
krauss@26056
   355
krauss@26056
   356
lemma drop_length [rule_format]:
krauss@26056
   357
     "l: list(A) ==> \<forall>i \<in> length(l). (EX z zs. drop(i,l) = Cons(z,zs))"
krauss@26056
   358
apply (erule list.induct, simp_all, safe)
krauss@26056
   359
apply (erule drop_length_Cons)
krauss@26056
   360
apply (rule natE)
krauss@26056
   361
apply (erule Ord_trans [OF asm_rl length_type Ord_nat], assumption, simp_all)
krauss@26056
   362
apply (blast intro: succ_in_naturalD length_type)
krauss@26056
   363
done
krauss@26056
   364
krauss@26056
   365
krauss@26056
   366
(*** theorems about app ***)
krauss@26056
   367
krauss@26056
   368
lemma app_right_Nil [simp]: "xs: list(A) ==> xs@Nil=xs"
krauss@26056
   369
by (erule list.induct, simp_all)
krauss@26056
   370
krauss@26056
   371
lemma app_assoc: "xs: list(A) ==> (xs@ys)@zs = xs@(ys@zs)"
krauss@26056
   372
by (induct_tac "xs", simp_all)
krauss@26056
   373
krauss@26056
   374
lemma flat_app_distrib: "ls: list(list(A)) ==> flat(ls@ms) = flat(ls)@flat(ms)"
krauss@26056
   375
apply (induct_tac "ls")
krauss@26056
   376
apply (simp_all (no_asm_simp) add: app_assoc)
krauss@26056
   377
done
krauss@26056
   378
krauss@26056
   379
(*** theorems about rev ***)
krauss@26056
   380
krauss@26056
   381
lemma rev_map_distrib: "l: list(A) ==> rev(map(h,l)) = map(h,rev(l))"
krauss@26056
   382
apply (induct_tac "l")
krauss@26056
   383
apply (simp_all (no_asm_simp) add: map_app_distrib)
krauss@26056
   384
done
krauss@26056
   385
krauss@26056
   386
(*Simplifier needs the premises as assumptions because rewriting will not
krauss@26056
   387
  instantiate the variable ?A in the rules' typing conditions; note that
krauss@26056
   388
  rev_type does not instantiate ?A.  Only the premises do.
krauss@26056
   389
*)
krauss@26056
   390
lemma rev_app_distrib:
krauss@26056
   391
     "[| xs: list(A);  ys: list(A) |] ==> rev(xs@ys) = rev(ys)@rev(xs)"
krauss@26056
   392
apply (erule list.induct)
krauss@26056
   393
apply (simp_all add: app_assoc)
krauss@26056
   394
done
krauss@26056
   395
krauss@26056
   396
lemma rev_rev_ident [simp]: "l: list(A) ==> rev(rev(l))=l"
krauss@26056
   397
apply (induct_tac "l")
krauss@26056
   398
apply (simp_all (no_asm_simp) add: rev_app_distrib)
krauss@26056
   399
done
krauss@26056
   400
krauss@26056
   401
lemma rev_flat: "ls: list(list(A)) ==> rev(flat(ls)) = flat(map(rev,rev(ls)))"
krauss@26056
   402
apply (induct_tac "ls")
krauss@26056
   403
apply (simp_all add: map_app_distrib flat_app_distrib rev_app_distrib)
krauss@26056
   404
done
krauss@26056
   405
krauss@26056
   406
krauss@26056
   407
(*** theorems about list_add ***)
krauss@26056
   408
krauss@26056
   409
lemma list_add_app:
krauss@26056
   410
     "[| xs: list(nat);  ys: list(nat) |]
krauss@26056
   411
      ==> list_add(xs@ys) = list_add(ys) #+ list_add(xs)"
krauss@26056
   412
apply (induct_tac "xs", simp_all)
krauss@26056
   413
done
krauss@26056
   414
krauss@26056
   415
lemma list_add_rev: "l: list(nat) ==> list_add(rev(l)) = list_add(l)"
krauss@26056
   416
apply (induct_tac "l")
krauss@26056
   417
apply (simp_all (no_asm_simp) add: list_add_app)
krauss@26056
   418
done
krauss@26056
   419
krauss@26056
   420
lemma list_add_flat:
krauss@26056
   421
     "ls: list(list(nat)) ==> list_add(flat(ls)) = list_add(map(list_add,ls))"
krauss@26056
   422
apply (induct_tac "ls")
krauss@26056
   423
apply (simp_all (no_asm_simp) add: list_add_app)
krauss@26056
   424
done
krauss@26056
   425
krauss@26056
   426
(** New induction rules **)
krauss@26056
   427
krauss@26056
   428
lemma list_append_induct [case_names Nil snoc, consumes 1]:
krauss@26056
   429
    "[| l: list(A);
krauss@26056
   430
        P(Nil);
krauss@26056
   431
        !!x y. [| x: A;  y: list(A);  P(y) |] ==> P(y @ [x])
krauss@26056
   432
     |] ==> P(l)"
krauss@26056
   433
apply (subgoal_tac "P(rev(rev(l)))", simp)
krauss@26056
   434
apply (erule rev_type [THEN list.induct], simp_all)
krauss@26056
   435
done
krauss@26056
   436
krauss@26056
   437
lemma list_complete_induct_lemma [rule_format]:
krauss@26056
   438
 assumes ih: 
krauss@26056
   439
    "\<And>l. [| l \<in> list(A); 
krauss@26056
   440
             \<forall>l' \<in> list(A). length(l') < length(l) --> P(l')|] 
krauss@26056
   441
          ==> P(l)"
krauss@26056
   442
  shows "n \<in> nat ==> \<forall>l \<in> list(A). length(l) < n --> P(l)"
krauss@26056
   443
apply (induct_tac n, simp)
krauss@26056
   444
apply (blast intro: ih elim!: leE) 
krauss@26056
   445
done
krauss@26056
   446
krauss@26056
   447
theorem list_complete_induct:
krauss@26056
   448
      "[| l \<in> list(A); 
krauss@26056
   449
          \<And>l. [| l \<in> list(A); 
krauss@26056
   450
                  \<forall>l' \<in> list(A). length(l') < length(l) --> P(l')|] 
krauss@26056
   451
               ==> P(l)
krauss@26056
   452
       |] ==> P(l)"
krauss@26056
   453
apply (rule list_complete_induct_lemma [of A]) 
krauss@26056
   454
   prefer 4 apply (rule le_refl, simp) 
krauss@26056
   455
  apply blast 
krauss@26056
   456
 apply simp 
krauss@26056
   457
apply assumption
krauss@26056
   458
done
krauss@26056
   459
krauss@26056
   460
krauss@26056
   461
(*** Thanks to Sidi Ehmety for these results about min, take, etc. ***)
krauss@26056
   462
krauss@26056
   463
(** min FIXME: replace by Int! **)
krauss@26056
   464
(* Min theorems are also true for i, j ordinals *)
krauss@26056
   465
lemma min_sym: "[| i:nat; j:nat |] ==> min(i,j)=min(j,i)"
krauss@26056
   466
apply (unfold min_def)
krauss@26056
   467
apply (auto dest!: not_lt_imp_le dest: lt_not_sym intro: le_anti_sym)
krauss@26056
   468
done
krauss@26056
   469
krauss@26056
   470
lemma min_type [simp,TC]: "[| i:nat; j:nat |] ==> min(i,j):nat"
krauss@26056
   471
by (unfold min_def, auto)
krauss@26056
   472
krauss@26056
   473
lemma min_0 [simp]: "i:nat ==> min(0,i) = 0"
krauss@26056
   474
apply (unfold min_def)
krauss@26056
   475
apply (auto dest: not_lt_imp_le)
krauss@26056
   476
done
krauss@26056
   477
krauss@26056
   478
lemma min_02 [simp]: "i:nat ==> min(i, 0) = 0"
krauss@26056
   479
apply (unfold min_def)
krauss@26056
   480
apply (auto dest: not_lt_imp_le)
krauss@26056
   481
done
krauss@26056
   482
krauss@26056
   483
lemma lt_min_iff: "[| i:nat; j:nat; k:nat |] ==> i<min(j,k) <-> i<j & i<k"
krauss@26056
   484
apply (unfold min_def)
krauss@26056
   485
apply (auto dest!: not_lt_imp_le intro: lt_trans2 lt_trans)
krauss@26056
   486
done
krauss@26056
   487
krauss@26056
   488
lemma min_succ_succ [simp]:
krauss@26056
   489
     "[| i:nat; j:nat |] ==>  min(succ(i), succ(j))= succ(min(i, j))"
krauss@26056
   490
apply (unfold min_def, auto)
krauss@26056
   491
done
krauss@26056
   492
krauss@26056
   493
(*** more theorems about lists ***)
krauss@26056
   494
krauss@26056
   495
(** filter **)
krauss@26056
   496
krauss@26056
   497
lemma filter_append [simp]:
krauss@26056
   498
     "xs:list(A) ==> filter(P, xs@ys) = filter(P, xs) @ filter(P, ys)"
krauss@26056
   499
by (induct_tac "xs", auto)
krauss@26056
   500
krauss@26056
   501
lemma filter_type [simp,TC]: "xs:list(A) ==> filter(P, xs):list(A)"
krauss@26056
   502
by (induct_tac "xs", auto)
krauss@26056
   503
krauss@26056
   504
lemma length_filter: "xs:list(A) ==> length(filter(P, xs)) le length(xs)"
krauss@26056
   505
apply (induct_tac "xs", auto)
krauss@26056
   506
apply (rule_tac j = "length (l) " in le_trans)
krauss@26056
   507
apply (auto simp add: le_iff)
krauss@26056
   508
done
krauss@26056
   509
krauss@26056
   510
lemma filter_is_subset: "xs:list(A) ==> set_of_list(filter(P,xs)) <= set_of_list(xs)"
krauss@26056
   511
by (induct_tac "xs", auto)
krauss@26056
   512
krauss@26056
   513
lemma filter_False [simp]: "xs:list(A) ==> filter(%p. False, xs) = Nil"
krauss@26056
   514
by (induct_tac "xs", auto)
krauss@26056
   515
krauss@26056
   516
lemma filter_True [simp]: "xs:list(A) ==> filter(%p. True, xs) = xs"
krauss@26056
   517
by (induct_tac "xs", auto)
krauss@26056
   518
krauss@26056
   519
(** length **)
krauss@26056
   520
krauss@26056
   521
lemma length_is_0_iff [simp]: "xs:list(A) ==> length(xs)=0 <-> xs=Nil"
krauss@26056
   522
by (erule list.induct, auto)
krauss@26056
   523
krauss@26056
   524
lemma length_is_0_iff2 [simp]: "xs:list(A) ==> 0 = length(xs) <-> xs=Nil"
krauss@26056
   525
by (erule list.induct, auto)
krauss@26056
   526
krauss@26056
   527
lemma length_tl [simp]: "xs:list(A) ==> length(tl(xs)) = length(xs) #- 1"
krauss@26056
   528
by (erule list.induct, auto)
krauss@26056
   529
krauss@26056
   530
lemma length_greater_0_iff: "xs:list(A) ==> 0<length(xs) <-> xs ~= Nil"
krauss@26056
   531
by (erule list.induct, auto)
krauss@26056
   532
krauss@26056
   533
lemma length_succ_iff: "xs:list(A) ==> length(xs)=succ(n) <-> (EX y ys. xs=Cons(y, ys) & length(ys)=n)"
krauss@26056
   534
by (erule list.induct, auto)
krauss@26056
   535
krauss@26056
   536
(** more theorems about append **)
krauss@26056
   537
krauss@26056
   538
lemma append_is_Nil_iff [simp]:
krauss@26056
   539
     "xs:list(A) ==> (xs@ys = Nil) <-> (xs=Nil & ys = Nil)"
krauss@26056
   540
by (erule list.induct, auto)
krauss@26056
   541
krauss@26056
   542
lemma append_is_Nil_iff2 [simp]:
krauss@26056
   543
     "xs:list(A) ==> (Nil = xs@ys) <-> (xs=Nil & ys = Nil)"
krauss@26056
   544
by (erule list.induct, auto)
krauss@26056
   545
krauss@26056
   546
lemma append_left_is_self_iff [simp]:
krauss@26056
   547
     "xs:list(A) ==> (xs@ys = xs) <-> (ys = Nil)"
krauss@26056
   548
by (erule list.induct, auto)
krauss@26056
   549
krauss@26056
   550
lemma append_left_is_self_iff2 [simp]:
krauss@26056
   551
     "xs:list(A) ==> (xs = xs@ys) <-> (ys = Nil)"
krauss@26056
   552
by (erule list.induct, auto)
krauss@26056
   553
krauss@26056
   554
(*TOO SLOW as a default simprule!*)
krauss@26056
   555
lemma append_left_is_Nil_iff [rule_format]:
krauss@26056
   556
     "[| xs:list(A); ys:list(A); zs:list(A) |] ==>
krauss@26056
   557
   length(ys)=length(zs) --> (xs@ys=zs <-> (xs=Nil & ys=zs))"
krauss@26056
   558
apply (erule list.induct)
krauss@26056
   559
apply (auto simp add: length_app)
krauss@26056
   560
done
krauss@26056
   561
krauss@26056
   562
(*TOO SLOW as a default simprule!*)
krauss@26056
   563
lemma append_left_is_Nil_iff2 [rule_format]:
krauss@26056
   564
     "[| xs:list(A); ys:list(A); zs:list(A) |] ==>
krauss@26056
   565
   length(ys)=length(zs) --> (zs=ys@xs <-> (xs=Nil & ys=zs))"
krauss@26056
   566
apply (erule list.induct)
krauss@26056
   567
apply (auto simp add: length_app)
krauss@26056
   568
done
krauss@26056
   569
krauss@26056
   570
lemma append_eq_append_iff [rule_format,simp]:
krauss@26056
   571
     "xs:list(A) ==> \<forall>ys \<in> list(A).
krauss@26056
   572
      length(xs)=length(ys) --> (xs@us = ys@vs) <-> (xs=ys & us=vs)"
krauss@26056
   573
apply (erule list.induct)
krauss@26056
   574
apply (simp (no_asm_simp))
krauss@26056
   575
apply clarify
krauss@26056
   576
apply (erule_tac a = ys in list.cases, auto)
krauss@26056
   577
done
krauss@26056
   578
krauss@26056
   579
lemma append_eq_append [rule_format]:
krauss@26056
   580
  "xs:list(A) ==>
krauss@26056
   581
   \<forall>ys \<in> list(A). \<forall>us \<in> list(A). \<forall>vs \<in> list(A).
krauss@26056
   582
   length(us) = length(vs) --> (xs@us = ys@vs) --> (xs=ys & us=vs)"
krauss@26056
   583
apply (induct_tac "xs")
krauss@26056
   584
apply (force simp add: length_app, clarify)
krauss@26056
   585
apply (erule_tac a = ys in list.cases, simp)
krauss@26056
   586
apply (subgoal_tac "Cons (a, l) @ us =vs")
krauss@26056
   587
 apply (drule rev_iffD1 [OF _ append_left_is_Nil_iff], simp_all, blast)
krauss@26056
   588
done
krauss@26056
   589
krauss@26056
   590
lemma append_eq_append_iff2 [simp]:
krauss@26056
   591
 "[| xs:list(A); ys:list(A); us:list(A); vs:list(A); length(us)=length(vs) |]
krauss@26056
   592
  ==>  xs@us = ys@vs <-> (xs=ys & us=vs)"
krauss@26056
   593
apply (rule iffI)
krauss@26056
   594
apply (rule append_eq_append, auto)
krauss@26056
   595
done
krauss@26056
   596
krauss@26056
   597
lemma append_self_iff [simp]:
krauss@26056
   598
     "[| xs:list(A); ys:list(A); zs:list(A) |] ==> xs@ys=xs@zs <-> ys=zs"
krauss@26056
   599
by simp
krauss@26056
   600
krauss@26056
   601
lemma append_self_iff2 [simp]:
krauss@26056
   602
     "[| xs:list(A); ys:list(A); zs:list(A) |] ==> ys@xs=zs@xs <-> ys=zs"
krauss@26056
   603
by simp
krauss@26056
   604
krauss@26056
   605
(* Can also be proved from append_eq_append_iff2,
krauss@26056
   606
but the proof requires two more hypotheses: x:A and y:A *)
krauss@26056
   607
lemma append1_eq_iff [rule_format,simp]:
krauss@26056
   608
     "xs:list(A) ==> \<forall>ys \<in> list(A). xs@[x] = ys@[y] <-> (xs = ys & x=y)"
krauss@26056
   609
apply (erule list.induct)  
krauss@26056
   610
 apply clarify 
krauss@26056
   611
 apply (erule list.cases)
krauss@26056
   612
 apply simp_all
krauss@26056
   613
txt{*Inductive step*}  
krauss@26056
   614
apply clarify 
krauss@26056
   615
apply (erule_tac a=ys in list.cases, simp_all)  
krauss@26056
   616
done
krauss@26056
   617
krauss@26056
   618
krauss@26056
   619
lemma append_right_is_self_iff [simp]:
krauss@26056
   620
     "[| xs:list(A); ys:list(A) |] ==> (xs@ys = ys) <-> (xs=Nil)"
krauss@26056
   621
by (simp (no_asm_simp) add: append_left_is_Nil_iff)
krauss@26056
   622
krauss@26056
   623
lemma append_right_is_self_iff2 [simp]:
krauss@26056
   624
     "[| xs:list(A); ys:list(A) |] ==> (ys = xs@ys) <-> (xs=Nil)"
krauss@26056
   625
apply (rule iffI)
krauss@26056
   626
apply (drule sym, auto) 
krauss@26056
   627
done
krauss@26056
   628
krauss@26056
   629
lemma hd_append [rule_format,simp]:
krauss@26056
   630
     "xs:list(A) ==> xs ~= Nil --> hd(xs @ ys) = hd(xs)"
krauss@26056
   631
by (induct_tac "xs", auto)
krauss@26056
   632
krauss@26056
   633
lemma tl_append [rule_format,simp]:
krauss@26056
   634
     "xs:list(A) ==> xs~=Nil --> tl(xs @ ys) = tl(xs)@ys"
krauss@26056
   635
by (induct_tac "xs", auto)
krauss@26056
   636
krauss@26056
   637
(** rev **)
krauss@26056
   638
lemma rev_is_Nil_iff [simp]: "xs:list(A) ==> (rev(xs) = Nil <-> xs = Nil)"
krauss@26056
   639
by (erule list.induct, auto)
krauss@26056
   640
krauss@26056
   641
lemma Nil_is_rev_iff [simp]: "xs:list(A) ==> (Nil = rev(xs) <-> xs = Nil)"
krauss@26056
   642
by (erule list.induct, auto)
krauss@26056
   643
krauss@26056
   644
lemma rev_is_rev_iff [rule_format,simp]:
krauss@26056
   645
     "xs:list(A) ==> \<forall>ys \<in> list(A). rev(xs)=rev(ys) <-> xs=ys"
krauss@26056
   646
apply (erule list.induct, force, clarify)
krauss@26056
   647
apply (erule_tac a = ys in list.cases, auto)
krauss@26056
   648
done
krauss@26056
   649
krauss@26056
   650
lemma rev_list_elim [rule_format]:
krauss@26056
   651
     "xs:list(A) ==>
krauss@26056
   652
      (xs=Nil --> P) --> (\<forall>ys \<in> list(A). \<forall>y \<in> A. xs =ys@[y] -->P)-->P"
krauss@26056
   653
by (erule list_append_induct, auto)
krauss@26056
   654
krauss@26056
   655
krauss@26056
   656
(** more theorems about drop **)
krauss@26056
   657
krauss@26056
   658
lemma length_drop [rule_format,simp]:
krauss@26056
   659
     "n:nat ==> \<forall>xs \<in> list(A). length(drop(n, xs)) = length(xs) #- n"
krauss@26056
   660
apply (erule nat_induct)
krauss@26056
   661
apply (auto elim: list.cases)
krauss@26056
   662
done
krauss@26056
   663
krauss@26056
   664
lemma drop_all [rule_format,simp]:
krauss@26056
   665
     "n:nat ==> \<forall>xs \<in> list(A). length(xs) le n --> drop(n, xs)=Nil"
krauss@26056
   666
apply (erule nat_induct)
krauss@26056
   667
apply (auto elim: list.cases)
krauss@26056
   668
done
krauss@26056
   669
krauss@26056
   670
lemma drop_append [rule_format]:
krauss@26056
   671
     "n:nat ==> 
krauss@26056
   672
      \<forall>xs \<in> list(A). drop(n, xs@ys) = drop(n,xs) @ drop(n #- length(xs), ys)"
krauss@26056
   673
apply (induct_tac "n")
krauss@26056
   674
apply (auto elim: list.cases)
krauss@26056
   675
done
krauss@26056
   676
krauss@26056
   677
lemma drop_drop:
krauss@26056
   678
    "m:nat ==> \<forall>xs \<in> list(A). \<forall>n \<in> nat. drop(n, drop(m, xs))=drop(n #+ m, xs)"
krauss@26056
   679
apply (induct_tac "m")
krauss@26056
   680
apply (auto elim: list.cases)
krauss@26056
   681
done
krauss@26056
   682
krauss@26056
   683
(** take **)
krauss@26056
   684
krauss@26056
   685
lemma take_0 [simp]: "xs:list(A) ==> take(0, xs) =  Nil"
krauss@26056
   686
apply (unfold take_def)
krauss@26056
   687
apply (erule list.induct, auto)
krauss@26056
   688
done
krauss@26056
   689
krauss@26056
   690
lemma take_succ_Cons [simp]:
krauss@26056
   691
    "n:nat ==> take(succ(n), Cons(a, xs)) = Cons(a, take(n, xs))"
krauss@26056
   692
by (simp add: take_def)
krauss@26056
   693
krauss@26056
   694
(* Needed for proving take_all *)
krauss@26056
   695
lemma take_Nil [simp]: "n:nat ==> take(n, Nil) = Nil"
krauss@26056
   696
by (unfold take_def, auto)
krauss@26056
   697
krauss@26056
   698
lemma take_all [rule_format,simp]:
krauss@26056
   699
     "n:nat ==> \<forall>xs \<in> list(A). length(xs) le n  --> take(n, xs) = xs"
krauss@26056
   700
apply (erule nat_induct)
krauss@26056
   701
apply (auto elim: list.cases) 
krauss@26056
   702
done
krauss@26056
   703
krauss@26056
   704
lemma take_type [rule_format,simp,TC]:
krauss@26056
   705
     "xs:list(A) ==> \<forall>n \<in> nat. take(n, xs):list(A)"
krauss@26056
   706
apply (erule list.induct, simp, clarify) 
krauss@26056
   707
apply (erule natE, auto)
krauss@26056
   708
done
krauss@26056
   709
krauss@26056
   710
lemma take_append [rule_format,simp]:
krauss@26056
   711
 "xs:list(A) ==>
krauss@26056
   712
  \<forall>ys \<in> list(A). \<forall>n \<in> nat. take(n, xs @ ys) =
krauss@26056
   713
                            take(n, xs) @ take(n #- length(xs), ys)"
krauss@26056
   714
apply (erule list.induct, simp, clarify) 
krauss@26056
   715
apply (erule natE, auto)
krauss@26056
   716
done
krauss@26056
   717
krauss@26056
   718
lemma take_take [rule_format]:
krauss@26056
   719
   "m : nat ==>
krauss@26056
   720
    \<forall>xs \<in> list(A). \<forall>n \<in> nat. take(n, take(m,xs))= take(min(n, m), xs)"
krauss@26056
   721
apply (induct_tac "m", auto)
krauss@26056
   722
apply (erule_tac a = xs in list.cases)
krauss@26056
   723
apply (auto simp add: take_Nil)
krauss@26056
   724
apply (erule_tac n=n in natE)
krauss@26056
   725
apply (auto intro: take_0 take_type)
krauss@26056
   726
done
krauss@26056
   727
krauss@26056
   728
(** nth **)
krauss@26056
   729
krauss@26056
   730
lemma nth_0 [simp]: "nth(0, Cons(a, l)) = a"
krauss@26056
   731
by (simp add: nth_def) 
krauss@26056
   732
krauss@26056
   733
lemma nth_Cons [simp]: "n:nat ==> nth(succ(n), Cons(a,l)) = nth(n,l)"
krauss@26056
   734
by (simp add: nth_def) 
krauss@26056
   735
krauss@26056
   736
lemma nth_empty [simp]: "nth(n, Nil) = 0"
krauss@26056
   737
by (simp add: nth_def) 
krauss@26056
   738
krauss@26056
   739
lemma nth_type [rule_format,simp,TC]:
krauss@26056
   740
     "xs:list(A) ==> \<forall>n. n < length(xs) --> nth(n,xs) : A"
krauss@26056
   741
apply (erule list.induct, simp, clarify)
krauss@26056
   742
apply (subgoal_tac "n \<in> nat")  
krauss@26056
   743
 apply (erule natE, auto dest!: le_in_nat)
krauss@26056
   744
done
krauss@26056
   745
krauss@26056
   746
lemma nth_eq_0 [rule_format]:
krauss@26056
   747
     "xs:list(A) ==> \<forall>n \<in> nat. length(xs) le n --> nth(n,xs) = 0"
krauss@26056
   748
apply (erule list.induct, simp, clarify) 
krauss@26056
   749
apply (erule natE, auto)
krauss@26056
   750
done
krauss@26056
   751
krauss@26056
   752
lemma nth_append [rule_format]:
krauss@26056
   753
  "xs:list(A) ==> 
krauss@26056
   754
   \<forall>n \<in> nat. nth(n, xs @ ys) = (if n < length(xs) then nth(n,xs)
krauss@26056
   755
                                else nth(n #- length(xs), ys))"
krauss@26056
   756
apply (induct_tac "xs", simp, clarify) 
krauss@26056
   757
apply (erule natE, auto)
krauss@26056
   758
done
krauss@26056
   759
krauss@26056
   760
lemma set_of_list_conv_nth:
krauss@26056
   761
    "xs:list(A)
krauss@26056
   762
     ==> set_of_list(xs) = {x:A. EX i:nat. i<length(xs) & x = nth(i,xs)}"
krauss@26056
   763
apply (induct_tac "xs", simp_all)
krauss@26056
   764
apply (rule equalityI, auto)
krauss@26056
   765
apply (rule_tac x = 0 in bexI, auto)
krauss@26056
   766
apply (erule natE, auto)
krauss@26056
   767
done
krauss@26056
   768
krauss@26056
   769
(* Other theorems about lists *)
krauss@26056
   770
krauss@26056
   771
lemma nth_take_lemma [rule_format]:
krauss@26056
   772
 "k:nat ==>
krauss@26056
   773
  \<forall>xs \<in> list(A). (\<forall>ys \<in> list(A). k le length(xs) --> k le length(ys) -->
krauss@26056
   774
      (\<forall>i \<in> nat. i<k --> nth(i,xs) = nth(i,ys))--> take(k,xs) = take(k,ys))"
krauss@26056
   775
apply (induct_tac "k")
krauss@26056
   776
apply (simp_all (no_asm_simp) add: lt_succ_eq_0_disj all_conj_distrib)
krauss@26056
   777
apply clarify
krauss@26056
   778
(*Both lists are non-empty*)
krauss@26056
   779
apply (erule_tac a=xs in list.cases, simp) 
krauss@26056
   780
apply (erule_tac a=ys in list.cases, clarify) 
krauss@26056
   781
apply (simp (no_asm_use) )
krauss@26056
   782
apply clarify
krauss@26056
   783
apply (simp (no_asm_simp))
krauss@26056
   784
apply (rule conjI, force)
krauss@26056
   785
apply (rename_tac y ys z zs) 
krauss@26056
   786
apply (drule_tac x = zs and x1 = ys in bspec [THEN bspec], auto)   
krauss@26056
   787
done
krauss@26056
   788
krauss@26056
   789
lemma nth_equalityI [rule_format]:
krauss@26056
   790
     "[| xs:list(A); ys:list(A); length(xs) = length(ys);
krauss@26056
   791
         \<forall>i \<in> nat. i < length(xs) --> nth(i,xs) = nth(i,ys) |]
krauss@26056
   792
      ==> xs = ys"
krauss@26056
   793
apply (subgoal_tac "length (xs) le length (ys) ")
krauss@26056
   794
apply (cut_tac k="length(xs)" and xs=xs and ys=ys in nth_take_lemma) 
krauss@26056
   795
apply (simp_all add: take_all)
krauss@26056
   796
done
krauss@26056
   797
krauss@26056
   798
(*The famous take-lemma*)
krauss@26056
   799
krauss@26056
   800
lemma take_equalityI [rule_format]:
krauss@26056
   801
    "[| xs:list(A); ys:list(A); (\<forall>i \<in> nat. take(i, xs) = take(i,ys)) |] 
krauss@26056
   802
     ==> xs = ys"
krauss@26056
   803
apply (case_tac "length (xs) le length (ys) ")
krauss@26056
   804
apply (drule_tac x = "length (ys) " in bspec)
krauss@26056
   805
apply (drule_tac [3] not_lt_imp_le)
krauss@26056
   806
apply (subgoal_tac [5] "length (ys) le length (xs) ")
krauss@26056
   807
apply (rule_tac [6] j = "succ (length (ys))" in le_trans)
krauss@26056
   808
apply (rule_tac [6] leI)
krauss@26056
   809
apply (drule_tac [5] x = "length (xs) " in bspec)
krauss@26056
   810
apply (simp_all add: take_all)
krauss@26056
   811
done
krauss@26056
   812
krauss@26056
   813
lemma nth_drop [rule_format]:
krauss@26056
   814
  "n:nat ==> \<forall>i \<in> nat. \<forall>xs \<in> list(A). nth(i, drop(n, xs)) = nth(n #+ i, xs)"
krauss@26056
   815
apply (induct_tac "n", simp_all, clarify)
krauss@26056
   816
apply (erule list.cases, auto)  
krauss@26056
   817
done
krauss@26056
   818
krauss@26056
   819
lemma take_succ [rule_format]:
krauss@26056
   820
  "xs\<in>list(A) 
krauss@26056
   821
   ==> \<forall>i. i < length(xs) --> take(succ(i), xs) = take(i,xs) @ [nth(i, xs)]"
krauss@26056
   822
apply (induct_tac "xs", auto)
krauss@26056
   823
apply (subgoal_tac "i\<in>nat") 
krauss@26056
   824
apply (erule natE)
krauss@26056
   825
apply (auto simp add: le_in_nat) 
krauss@26056
   826
done
krauss@26056
   827
krauss@26056
   828
lemma take_add [rule_format]:
krauss@26056
   829
     "[|xs\<in>list(A); j\<in>nat|] 
krauss@26056
   830
      ==> \<forall>i\<in>nat. take(i #+ j, xs) = take(i,xs) @ take(j, drop(i,xs))"
krauss@26056
   831
apply (induct_tac "xs", simp_all, clarify)
krauss@26056
   832
apply (erule_tac n = i in natE, simp_all)
krauss@26056
   833
done
krauss@26056
   834
krauss@26056
   835
lemma length_take:
krauss@26056
   836
     "l\<in>list(A) ==> \<forall>n\<in>nat. length(take(n,l)) = min(n, length(l))"
krauss@26056
   837
apply (induct_tac "l", safe, simp_all)
krauss@26056
   838
apply (erule natE, simp_all)
krauss@26056
   839
done
krauss@26056
   840
krauss@26056
   841
subsection{*The function zip*}
krauss@26056
   842
krauss@26056
   843
text{*Crafty definition to eliminate a type argument*}
krauss@26056
   844
krauss@26056
   845
consts
krauss@26056
   846
  zip_aux        :: "[i,i]=>i"
krauss@26056
   847
krauss@26056
   848
primrec (*explicit lambda is required because both arguments of "un" vary*)
krauss@26056
   849
  "zip_aux(B,[]) =
krauss@26056
   850
     (\<lambda>ys \<in> list(B). list_case([], %y l. [], ys))"
krauss@26056
   851
krauss@26056
   852
  "zip_aux(B,Cons(x,l)) =
krauss@26056
   853
     (\<lambda>ys \<in> list(B).
krauss@26056
   854
        list_case(Nil, %y zs. Cons(<x,y>, zip_aux(B,l)`zs), ys))"
krauss@26056
   855
krauss@26056
   856
definition
krauss@26056
   857
  zip :: "[i, i]=>i"  where
krauss@26056
   858
   "zip(xs, ys) == zip_aux(set_of_list(ys),xs)`ys"
krauss@26056
   859
krauss@26056
   860
krauss@26056
   861
(* zip equations *)
krauss@26056
   862
krauss@26056
   863
lemma list_on_set_of_list: "xs \<in> list(A) ==> xs \<in> list(set_of_list(xs))"
krauss@26056
   864
apply (induct_tac xs, simp_all) 
krauss@26056
   865
apply (blast intro: list_mono [THEN subsetD]) 
krauss@26056
   866
done
krauss@26056
   867
krauss@26056
   868
lemma zip_Nil [simp]: "ys:list(A) ==> zip(Nil, ys)=Nil"
krauss@26056
   869
apply (simp add: zip_def list_on_set_of_list [of _ A])
krauss@26056
   870
apply (erule list.cases, simp_all) 
krauss@26056
   871
done
krauss@26056
   872
krauss@26056
   873
lemma zip_Nil2 [simp]: "xs:list(A) ==> zip(xs, Nil)=Nil"
krauss@26056
   874
apply (simp add: zip_def list_on_set_of_list [of _ A])
krauss@26056
   875
apply (erule list.cases, simp_all) 
krauss@26056
   876
done
krauss@26056
   877
krauss@26056
   878
lemma zip_aux_unique [rule_format]:
krauss@26056
   879
     "[|B<=C;  xs \<in> list(A)|] 
krauss@26056
   880
      ==> \<forall>ys \<in> list(B). zip_aux(C,xs) ` ys = zip_aux(B,xs) ` ys"
krauss@26056
   881
apply (induct_tac xs) 
krauss@26056
   882
 apply simp_all 
krauss@26056
   883
 apply (blast intro: list_mono [THEN subsetD], clarify) 
krauss@26056
   884
apply (erule_tac a=ys in list.cases, auto) 
krauss@26056
   885
apply (blast intro: list_mono [THEN subsetD]) 
krauss@26056
   886
done
krauss@26056
   887
krauss@26056
   888
lemma zip_Cons_Cons [simp]:
krauss@26056
   889
     "[| xs:list(A); ys:list(B); x:A; y:B |] ==>
krauss@26056
   890
      zip(Cons(x,xs), Cons(y, ys)) = Cons(<x,y>, zip(xs, ys))"
krauss@26056
   891
apply (simp add: zip_def, auto) 
krauss@26056
   892
apply (rule zip_aux_unique, auto) 
krauss@26056
   893
apply (simp add: list_on_set_of_list [of _ B])
krauss@26056
   894
apply (blast intro: list_on_set_of_list list_mono [THEN subsetD]) 
krauss@26056
   895
done
krauss@26056
   896
krauss@26056
   897
lemma zip_type [rule_format,simp,TC]:
krauss@26056
   898
     "xs:list(A) ==> \<forall>ys \<in> list(B). zip(xs, ys):list(A*B)"
krauss@26056
   899
apply (induct_tac "xs")
krauss@26056
   900
apply (simp (no_asm))
krauss@26056
   901
apply clarify
krauss@26056
   902
apply (erule_tac a = ys in list.cases, auto)
krauss@26056
   903
done
krauss@26056
   904
krauss@26056
   905
(* zip length *)
krauss@26056
   906
lemma length_zip [rule_format,simp]:
krauss@26056
   907
     "xs:list(A) ==> \<forall>ys \<in> list(B). length(zip(xs,ys)) =
krauss@26056
   908
                                     min(length(xs), length(ys))"
krauss@26056
   909
apply (unfold min_def)
krauss@26056
   910
apply (induct_tac "xs", simp_all, clarify) 
krauss@26056
   911
apply (erule_tac a = ys in list.cases, auto)
krauss@26056
   912
done
krauss@26056
   913
krauss@26056
   914
lemma zip_append1 [rule_format]:
krauss@26056
   915
 "[| ys:list(A); zs:list(B) |] ==>
krauss@26056
   916
  \<forall>xs \<in> list(A). zip(xs @ ys, zs) = 
krauss@26056
   917
                 zip(xs, take(length(xs), zs)) @ zip(ys, drop(length(xs),zs))"
krauss@26056
   918
apply (induct_tac "zs", force, clarify) 
krauss@26056
   919
apply (erule_tac a = xs in list.cases, simp_all) 
krauss@26056
   920
done
krauss@26056
   921
krauss@26056
   922
lemma zip_append2 [rule_format]:
krauss@26056
   923
 "[| xs:list(A); zs:list(B) |] ==> \<forall>ys \<in> list(B). zip(xs, ys@zs) =
krauss@26056
   924
       zip(take(length(ys), xs), ys) @ zip(drop(length(ys), xs), zs)"
krauss@26056
   925
apply (induct_tac "xs", force, clarify) 
krauss@26056
   926
apply (erule_tac a = ys in list.cases, auto)
krauss@26056
   927
done
krauss@26056
   928
krauss@26056
   929
lemma zip_append [simp]:
krauss@26056
   930
 "[| length(xs) = length(us); length(ys) = length(vs);
krauss@26056
   931
     xs:list(A); us:list(B); ys:list(A); vs:list(B) |] 
krauss@26056
   932
  ==> zip(xs@ys,us@vs) = zip(xs, us) @ zip(ys, vs)"
krauss@26056
   933
by (simp (no_asm_simp) add: zip_append1 drop_append diff_self_eq_0)
krauss@26056
   934
krauss@26056
   935
krauss@26056
   936
lemma zip_rev [rule_format,simp]:
krauss@26056
   937
 "ys:list(B) ==> \<forall>xs \<in> list(A).
krauss@26056
   938
    length(xs) = length(ys) --> zip(rev(xs), rev(ys)) = rev(zip(xs, ys))"
krauss@26056
   939
apply (induct_tac "ys", force, clarify) 
krauss@26056
   940
apply (erule_tac a = xs in list.cases)
krauss@26056
   941
apply (auto simp add: length_rev)
krauss@26056
   942
done
krauss@26056
   943
krauss@26056
   944
lemma nth_zip [rule_format,simp]:
krauss@26056
   945
   "ys:list(B) ==> \<forall>i \<in> nat. \<forall>xs \<in> list(A).
krauss@26056
   946
                    i < length(xs) --> i < length(ys) -->
krauss@26056
   947
                    nth(i,zip(xs, ys)) = <nth(i,xs),nth(i, ys)>"
krauss@26056
   948
apply (induct_tac "ys", force, clarify) 
krauss@26056
   949
apply (erule_tac a = xs in list.cases, simp) 
krauss@26056
   950
apply (auto elim: natE)
krauss@26056
   951
done
krauss@26056
   952
krauss@26056
   953
lemma set_of_list_zip [rule_format]:
krauss@26056
   954
     "[| xs:list(A); ys:list(B); i:nat |]
krauss@26056
   955
      ==> set_of_list(zip(xs, ys)) =
krauss@26056
   956
          {<x, y>:A*B. EX i:nat. i < min(length(xs), length(ys))
krauss@26056
   957
          & x = nth(i, xs) & y = nth(i, ys)}"
krauss@26056
   958
by (force intro!: Collect_cong simp add: lt_min_iff set_of_list_conv_nth)
krauss@26056
   959
krauss@26056
   960
(** list_update **)
krauss@26056
   961
krauss@26056
   962
lemma list_update_Nil [simp]: "i:nat ==>list_update(Nil, i, v) = Nil"
krauss@26056
   963
by (unfold list_update_def, auto)
krauss@26056
   964
krauss@26056
   965
lemma list_update_Cons_0 [simp]: "list_update(Cons(x, xs), 0, v)= Cons(v, xs)"
krauss@26056
   966
by (unfold list_update_def, auto)
krauss@26056
   967
krauss@26056
   968
lemma list_update_Cons_succ [simp]:
krauss@26056
   969
  "n:nat ==>
krauss@26056
   970
    list_update(Cons(x, xs), succ(n), v)= Cons(x, list_update(xs, n, v))"
krauss@26056
   971
apply (unfold list_update_def, auto)
krauss@26056
   972
done
krauss@26056
   973
krauss@26056
   974
lemma list_update_type [rule_format,simp,TC]:
krauss@26056
   975
     "[| xs:list(A); v:A |] ==> \<forall>n \<in> nat. list_update(xs, n, v):list(A)"
krauss@26056
   976
apply (induct_tac "xs")
krauss@26056
   977
apply (simp (no_asm))
krauss@26056
   978
apply clarify
krauss@26056
   979
apply (erule natE, auto)
krauss@26056
   980
done
krauss@26056
   981
krauss@26056
   982
lemma length_list_update [rule_format,simp]:
krauss@26056
   983
     "xs:list(A) ==> \<forall>i \<in> nat. length(list_update(xs, i, v))=length(xs)"
krauss@26056
   984
apply (induct_tac "xs")
krauss@26056
   985
apply (simp (no_asm))
krauss@26056
   986
apply clarify
krauss@26056
   987
apply (erule natE, auto)
krauss@26056
   988
done
krauss@26056
   989
krauss@26056
   990
lemma nth_list_update [rule_format]:
krauss@26056
   991
     "[| xs:list(A) |] ==> \<forall>i \<in> nat. \<forall>j \<in> nat. i < length(xs)  -->
krauss@26056
   992
         nth(j, list_update(xs, i, x)) = (if i=j then x else nth(j, xs))"
krauss@26056
   993
apply (induct_tac "xs")
krauss@26056
   994
 apply simp_all
krauss@26056
   995
apply clarify
krauss@26056
   996
apply (rename_tac i j) 
krauss@26056
   997
apply (erule_tac n=i in natE) 
krauss@26056
   998
apply (erule_tac [2] n=j in natE)
krauss@26056
   999
apply (erule_tac n=j in natE, simp_all, force) 
krauss@26056
  1000
done
krauss@26056
  1001
krauss@26056
  1002
lemma nth_list_update_eq [simp]:
krauss@26056
  1003
     "[| i < length(xs); xs:list(A) |] ==> nth(i, list_update(xs, i,x)) = x"
krauss@26056
  1004
by (simp (no_asm_simp) add: lt_length_in_nat nth_list_update)
krauss@26056
  1005
krauss@26056
  1006
krauss@26056
  1007
lemma nth_list_update_neq [rule_format,simp]:
krauss@26056
  1008
  "xs:list(A) ==> 
krauss@26056
  1009
     \<forall>i \<in> nat. \<forall>j \<in> nat. i ~= j --> nth(j, list_update(xs,i,x)) = nth(j,xs)"
krauss@26056
  1010
apply (induct_tac "xs")
krauss@26056
  1011
 apply (simp (no_asm))
krauss@26056
  1012
apply clarify
krauss@26056
  1013
apply (erule natE)
krauss@26056
  1014
apply (erule_tac [2] natE, simp_all) 
krauss@26056
  1015
apply (erule natE, simp_all)
krauss@26056
  1016
done
krauss@26056
  1017
krauss@26056
  1018
lemma list_update_overwrite [rule_format,simp]:
krauss@26056
  1019
     "xs:list(A) ==> \<forall>i \<in> nat. i < length(xs)
krauss@26056
  1020
   --> list_update(list_update(xs, i, x), i, y) = list_update(xs, i,y)"
krauss@26056
  1021
apply (induct_tac "xs")
krauss@26056
  1022
 apply (simp (no_asm))
krauss@26056
  1023
apply clarify
krauss@26056
  1024
apply (erule natE, auto)
krauss@26056
  1025
done
krauss@26056
  1026
krauss@26056
  1027
lemma list_update_same_conv [rule_format]:
krauss@26056
  1028
     "xs:list(A) ==> 
krauss@26056
  1029
      \<forall>i \<in> nat. i < length(xs) --> 
krauss@26056
  1030
                 (list_update(xs, i, x) = xs) <-> (nth(i, xs) = x)"
krauss@26056
  1031
apply (induct_tac "xs")
krauss@26056
  1032
 apply (simp (no_asm))
krauss@26056
  1033
apply clarify
krauss@26056
  1034
apply (erule natE, auto)
krauss@26056
  1035
done
krauss@26056
  1036
krauss@26056
  1037
lemma update_zip [rule_format]:
krauss@26056
  1038
     "ys:list(B) ==> 
krauss@26056
  1039
      \<forall>i \<in> nat. \<forall>xy \<in> A*B. \<forall>xs \<in> list(A).
krauss@26056
  1040
        length(xs) = length(ys) -->
krauss@26056
  1041
        list_update(zip(xs, ys), i, xy) = zip(list_update(xs, i, fst(xy)),
krauss@26056
  1042
                                              list_update(ys, i, snd(xy)))"
krauss@26056
  1043
apply (induct_tac "ys")
krauss@26056
  1044
 apply auto
krauss@26056
  1045
apply (erule_tac a = xs in list.cases)
krauss@26056
  1046
apply (auto elim: natE)
krauss@26056
  1047
done
krauss@26056
  1048
krauss@26056
  1049
lemma set_update_subset_cons [rule_format]:
krauss@26056
  1050
  "xs:list(A) ==> 
krauss@26056
  1051
   \<forall>i \<in> nat. set_of_list(list_update(xs, i, x)) <= cons(x, set_of_list(xs))"
krauss@26056
  1052
apply (induct_tac "xs")
krauss@26056
  1053
 apply simp
krauss@26056
  1054
apply (rule ballI)
krauss@26056
  1055
apply (erule natE, simp_all, auto)
krauss@26056
  1056
done
krauss@26056
  1057
krauss@26056
  1058
lemma set_of_list_update_subsetI:
krauss@26056
  1059
     "[| set_of_list(xs) <= A; xs:list(A); x:A; i:nat|]
krauss@26056
  1060
   ==> set_of_list(list_update(xs, i,x)) <= A"
krauss@26056
  1061
apply (rule subset_trans)
krauss@26056
  1062
apply (rule set_update_subset_cons, auto)
krauss@26056
  1063
done
krauss@26056
  1064
krauss@26056
  1065
(** upt **)
krauss@26056
  1066
krauss@26056
  1067
lemma upt_rec:
krauss@26056
  1068
     "j:nat ==> upt(i,j) = (if i<j then Cons(i, upt(succ(i), j)) else Nil)"
krauss@26056
  1069
apply (induct_tac "j", auto)
krauss@26056
  1070
apply (drule not_lt_imp_le)
krauss@26056
  1071
apply (auto simp: lt_Ord intro: le_anti_sym)
krauss@26056
  1072
done
krauss@26056
  1073
krauss@26056
  1074
lemma upt_conv_Nil [simp]: "[| j le i; j:nat |] ==> upt(i,j) = Nil"
krauss@26056
  1075
apply (subst upt_rec, auto)
krauss@26056
  1076
apply (auto simp add: le_iff)
krauss@26056
  1077
apply (drule lt_asym [THEN notE], auto)
krauss@26056
  1078
done
krauss@26056
  1079
krauss@26056
  1080
(*Only needed if upt_Suc is deleted from the simpset*)
krauss@26056
  1081
lemma upt_succ_append:
krauss@26056
  1082
     "[| i le j; j:nat |] ==> upt(i,succ(j)) = upt(i, j)@[j]"
krauss@26056
  1083
by simp
krauss@26056
  1084
krauss@26056
  1085
lemma upt_conv_Cons:
krauss@26056
  1086
     "[| i<j; j:nat |]  ==> upt(i,j) = Cons(i,upt(succ(i),j))"
krauss@26056
  1087
apply (rule trans)
krauss@26056
  1088
apply (rule upt_rec, auto)
krauss@26056
  1089
done
krauss@26056
  1090
krauss@26056
  1091
lemma upt_type [simp,TC]: "j:nat ==> upt(i,j):list(nat)"
krauss@26056
  1092
by (induct_tac "j", auto)
krauss@26056
  1093
krauss@26056
  1094
(*LOOPS as a simprule, since j<=j*)
krauss@26056
  1095
lemma upt_add_eq_append:
krauss@26056
  1096
     "[| i le j; j:nat; k:nat |] ==> upt(i, j #+k) = upt(i,j)@upt(j,j#+k)"
krauss@26056
  1097
apply (induct_tac "k")
krauss@26056
  1098
apply (auto simp add: app_assoc app_type)
krauss@26056
  1099
apply (rule_tac j = j in le_trans, auto)
krauss@26056
  1100
done
krauss@26056
  1101
krauss@26056
  1102
lemma length_upt [simp]: "[| i:nat; j:nat |] ==>length(upt(i,j)) = j #- i"
krauss@26056
  1103
apply (induct_tac "j")
krauss@26056
  1104
apply (rule_tac [2] sym)
krauss@26056
  1105
apply (auto dest!: not_lt_imp_le simp add: diff_succ diff_is_0_iff)
krauss@26056
  1106
done
krauss@26056
  1107
krauss@26056
  1108
lemma nth_upt [rule_format,simp]:
krauss@26056
  1109
     "[| i:nat; j:nat; k:nat |] ==> i #+ k < j --> nth(k, upt(i,j)) = i #+ k"
krauss@26056
  1110
apply (induct_tac "j", simp)
krauss@26056
  1111
apply (simp add: nth_append le_iff)
krauss@26056
  1112
apply (auto dest!: not_lt_imp_le 
krauss@26056
  1113
            simp add: nth_append less_diff_conv add_commute)
krauss@26056
  1114
done
krauss@26056
  1115
krauss@26056
  1116
lemma take_upt [rule_format,simp]:
krauss@26056
  1117
     "[| m:nat; n:nat |] ==>
krauss@26056
  1118
         \<forall>i \<in> nat. i #+ m le n --> take(m, upt(i,n)) = upt(i,i#+m)"
krauss@26056
  1119
apply (induct_tac "m")
krauss@26056
  1120
apply (simp (no_asm_simp) add: take_0)
krauss@26056
  1121
apply clarify
krauss@26056
  1122
apply (subst upt_rec, simp) 
krauss@26056
  1123
apply (rule sym)
krauss@26056
  1124
apply (subst upt_rec, simp) 
krauss@26056
  1125
apply (simp_all del: upt.simps)
krauss@26056
  1126
apply (rule_tac j = "succ (i #+ x) " in lt_trans2)
krauss@26056
  1127
apply auto
krauss@26056
  1128
done
krauss@26056
  1129
krauss@26056
  1130
lemma map_succ_upt:
krauss@26056
  1131
     "[| m:nat; n:nat |] ==> map(succ, upt(m,n))= upt(succ(m), succ(n))"
krauss@26056
  1132
apply (induct_tac "n")
krauss@26056
  1133
apply (auto simp add: map_app_distrib)
krauss@26056
  1134
done
krauss@26056
  1135
krauss@26056
  1136
lemma nth_map [rule_format,simp]:
krauss@26056
  1137
     "xs:list(A) ==>
krauss@26056
  1138
      \<forall>n \<in> nat. n < length(xs) --> nth(n, map(f, xs)) = f(nth(n, xs))"
krauss@26056
  1139
apply (induct_tac "xs", simp)
krauss@26056
  1140
apply (rule ballI)
krauss@26056
  1141
apply (induct_tac "n", auto)
krauss@26056
  1142
done
krauss@26056
  1143
krauss@26056
  1144
lemma nth_map_upt [rule_format]:
krauss@26056
  1145
     "[| m:nat; n:nat |] ==>
krauss@26056
  1146
      \<forall>i \<in> nat. i < n #- m --> nth(i, map(f, upt(m,n))) = f(m #+ i)"
krauss@26056
  1147
apply (rule_tac n = m and m = n in diff_induct, typecheck, simp, simp) 
krauss@26056
  1148
apply (subst map_succ_upt [symmetric], simp_all, clarify) 
krauss@26056
  1149
apply (subgoal_tac "i < length (upt (0, x))")
krauss@26056
  1150
 prefer 2 
krauss@26056
  1151
 apply (simp add: less_diff_conv) 
krauss@26056
  1152
 apply (rule_tac j = "succ (i #+ y) " in lt_trans2)
krauss@26056
  1153
  apply simp 
krauss@26056
  1154
 apply simp 
krauss@26056
  1155
apply (subgoal_tac "i < length (upt (y, x))")
krauss@26056
  1156
 apply (simp_all add: add_commute less_diff_conv)
krauss@26056
  1157
done
krauss@26056
  1158
krauss@26056
  1159
(** sublist (a generalization of nth to sets) **)
krauss@26056
  1160
krauss@26056
  1161
definition
krauss@26056
  1162
  sublist :: "[i, i] => i"  where
krauss@26056
  1163
    "sublist(xs, A)==
krauss@26056
  1164
     map(fst, (filter(%p. snd(p): A, zip(xs, upt(0,length(xs))))))"
krauss@26056
  1165
krauss@26056
  1166
lemma sublist_0 [simp]: "xs:list(A) ==>sublist(xs, 0) =Nil"
krauss@26056
  1167
by (unfold sublist_def, auto)
krauss@26056
  1168
krauss@26056
  1169
lemma sublist_Nil [simp]: "sublist(Nil, A) = Nil"
krauss@26056
  1170
by (unfold sublist_def, auto)
krauss@26056
  1171
krauss@26056
  1172
lemma sublist_shift_lemma:
krauss@26056
  1173
 "[| xs:list(B); i:nat |] ==>
krauss@26056
  1174
  map(fst, filter(%p. snd(p):A, zip(xs, upt(i,i #+ length(xs))))) =
krauss@26056
  1175
  map(fst, filter(%p. snd(p):nat & snd(p) #+ i:A, zip(xs,upt(0,length(xs)))))"
krauss@26056
  1176
apply (erule list_append_induct)
krauss@26056
  1177
apply (simp (no_asm_simp))
krauss@26056
  1178
apply (auto simp add: add_commute length_app filter_append map_app_distrib)
krauss@26056
  1179
done
krauss@26056
  1180
krauss@26056
  1181
lemma sublist_type [simp,TC]:
krauss@26056
  1182
     "xs:list(B) ==> sublist(xs, A):list(B)"
krauss@26056
  1183
apply (unfold sublist_def)
krauss@26056
  1184
apply (induct_tac "xs")
krauss@26056
  1185
apply (auto simp add: filter_append map_app_distrib)
krauss@26056
  1186
done
krauss@26056
  1187
krauss@26056
  1188
lemma upt_add_eq_append2:
krauss@26056
  1189
     "[| i:nat; j:nat |] ==> upt(0, i #+ j) = upt(0, i) @ upt(i, i #+ j)"
krauss@26056
  1190
by (simp add: upt_add_eq_append [of 0] nat_0_le)
krauss@26056
  1191
krauss@26056
  1192
lemma sublist_append:
krauss@26056
  1193
 "[| xs:list(B); ys:list(B)  |] ==>
krauss@26056
  1194
  sublist(xs@ys, A) = sublist(xs, A) @ sublist(ys, {j:nat. j #+ length(xs): A})"
krauss@26056
  1195
apply (unfold sublist_def)
krauss@26056
  1196
apply (erule_tac l = ys in list_append_induct, simp)
krauss@26056
  1197
apply (simp (no_asm_simp) add: upt_add_eq_append2 app_assoc [symmetric])
krauss@26056
  1198
apply (auto simp add: sublist_shift_lemma length_type map_app_distrib app_assoc)
krauss@26056
  1199
apply (simp_all add: add_commute)
krauss@26056
  1200
done
krauss@26056
  1201
krauss@26056
  1202
krauss@26056
  1203
lemma sublist_Cons:
krauss@26056
  1204
     "[| xs:list(B); x:B |] ==>
krauss@26056
  1205
      sublist(Cons(x, xs), A) = 
krauss@26056
  1206
      (if 0:A then [x] else []) @ sublist(xs, {j:nat. succ(j) : A})"
krauss@26056
  1207
apply (erule_tac l = xs in list_append_induct)
krauss@26056
  1208
apply (simp (no_asm_simp) add: sublist_def)  
krauss@26056
  1209
apply (simp del: app_Cons add: app_Cons [symmetric] sublist_append, simp) 
krauss@26056
  1210
done
krauss@26056
  1211
krauss@26056
  1212
lemma sublist_singleton [simp]:
krauss@26056
  1213
     "sublist([x], A) = (if 0 : A then [x] else [])"
krauss@26056
  1214
by (simp add: sublist_Cons)
krauss@26056
  1215
krauss@26056
  1216
lemma sublist_upt_eq_take [rule_format, simp]:
krauss@26056
  1217
    "xs:list(A) ==> ALL n:nat. sublist(xs,n) = take(n,xs)"
krauss@26056
  1218
apply (erule list.induct, simp) 
krauss@26056
  1219
apply (clarify ); 
krauss@26056
  1220
apply (erule natE) 
krauss@26056
  1221
apply (simp_all add: nat_eq_Collect_lt Ord_mem_iff_lt sublist_Cons)
krauss@26056
  1222
done
krauss@26056
  1223
krauss@26056
  1224
lemma sublist_Int_eq:
krauss@26056
  1225
     "xs : list(B) ==> sublist(xs, A \<inter> nat) = sublist(xs, A)"
krauss@26056
  1226
apply (erule list.induct)
krauss@26056
  1227
apply (simp_all add: sublist_Cons) 
krauss@26056
  1228
done
krauss@26056
  1229
krauss@26056
  1230
text{*Repetition of a List Element*}
krauss@26056
  1231
krauss@26056
  1232
consts   repeat :: "[i,i]=>i"
krauss@26056
  1233
primrec
krauss@26056
  1234
  "repeat(a,0) = []"
krauss@26056
  1235
krauss@26056
  1236
  "repeat(a,succ(n)) = Cons(a,repeat(a,n))"
krauss@26056
  1237
krauss@26056
  1238
lemma length_repeat: "n \<in> nat ==> length(repeat(a,n)) = n"
krauss@26056
  1239
by (induct_tac n, auto)
krauss@26056
  1240
krauss@26056
  1241
lemma repeat_succ_app: "n \<in> nat ==> repeat(a,succ(n)) = repeat(a,n) @ [a]"
krauss@26056
  1242
apply (induct_tac n)
krauss@26056
  1243
apply (simp_all del: app_Cons add: app_Cons [symmetric])
krauss@26056
  1244
done
krauss@26056
  1245
krauss@26056
  1246
lemma repeat_type [TC]: "[|a \<in> A; n \<in> nat|] ==> repeat(a,n) \<in> list(A)"
krauss@26056
  1247
by (induct_tac n, auto)
krauss@26056
  1248
krauss@26056
  1249
end