src/HOL/List.thy
changeset 69593 3dda49e08b9d
parent 69349 7cef9e386ffe
child 69700 7a92cbec7030
equal deleted inserted replaced
69592:a80d8ec6c998 69593:3dda49e08b9d
   180 primrec find :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a option" where
   180 primrec find :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'a option" where
   181 "find _ [] = None" |
   181 "find _ [] = None" |
   182 "find P (x#xs) = (if P x then Some x else find P xs)"
   182 "find P (x#xs) = (if P x then Some x else find P xs)"
   183 
   183 
   184 text \<open>In the context of multisets, \<open>count_list\<close> is equivalent to
   184 text \<open>In the context of multisets, \<open>count_list\<close> is equivalent to
   185   @{term "count \<circ> mset"} and it it advisable to use the latter.\<close>
   185   \<^term>\<open>count \<circ> mset\<close> and it it advisable to use the latter.\<close>
   186 primrec count_list :: "'a list \<Rightarrow> 'a \<Rightarrow> nat" where
   186 primrec count_list :: "'a list \<Rightarrow> 'a \<Rightarrow> nat" where
   187 "count_list [] y = 0" |
   187 "count_list [] y = 0" |
   188 "count_list (x#xs) y = (if x=y then count_list xs y + 1 else count_list xs y)"
   188 "count_list (x#xs) y = (if x=y then count_list xs y + 1 else count_list xs y)"
   189 
   189 
   190 definition
   190 definition
   271 | "shuffles xs [] = {xs}"
   271 | "shuffles xs [] = {xs}"
   272 | "shuffles (x # xs) (y # ys) = (#) x ` shuffles xs (y # ys) \<union> (#) y ` shuffles (x # xs) ys"
   272 | "shuffles (x # xs) (y # ys) = (#) x ` shuffles xs (y # ys) \<union> (#) y ` shuffles (x # xs) ys"
   273   by pat_completeness simp_all
   273   by pat_completeness simp_all
   274 termination by lexicographic_order
   274 termination by lexicographic_order
   275 
   275 
   276 text\<open>Use only if you cannot use @{const Min} instead:\<close>
   276 text\<open>Use only if you cannot use \<^const>\<open>Min\<close> instead:\<close>
   277 fun min_list :: "'a::ord list \<Rightarrow> 'a" where
   277 fun min_list :: "'a::ord list \<Rightarrow> 'a" where
   278 "min_list (x # xs) = (case xs of [] \<Rightarrow> x | _ \<Rightarrow> min x (min_list xs))"
   278 "min_list (x # xs) = (case xs of [] \<Rightarrow> x | _ \<Rightarrow> min x (min_list xs))"
   279 
   279 
   280 text\<open>Returns first minimum:\<close>
   280 text\<open>Returns first minimum:\<close>
   281 fun arg_min_list :: "('a \<Rightarrow> ('b::linorder)) \<Rightarrow> 'a list \<Rightarrow> 'a" where
   281 fun arg_min_list :: "('a \<Rightarrow> ('b::linorder)) \<Rightarrow> 'a list \<Rightarrow> 'a" where
   414 \end{description}
   414 \end{description}
   415 
   415 
   416 Just like in Haskell, list comprehension is just a shorthand. To avoid
   416 Just like in Haskell, list comprehension is just a shorthand. To avoid
   417 misunderstandings, the translation into desugared form is not reversed
   417 misunderstandings, the translation into desugared form is not reversed
   418 upon output. Note that the translation of \<open>[e. x \<leftarrow> xs]\<close> is
   418 upon output. Note that the translation of \<open>[e. x \<leftarrow> xs]\<close> is
   419 optmized to @{term"map (%x. e) xs"}.
   419 optmized to \<^term>\<open>map (%x. e) xs\<close>.
   420 
   420 
   421 It is easy to write short list comprehensions which stand for complex
   421 It is easy to write short list comprehensions which stand for complex
   422 expressions. During proofs, they may become unreadable (and
   422 expressions. During proofs, they may become unreadable (and
   423 mangled). In such cases it can be advisable to introduce separate
   423 mangled). In such cases it can be advisable to introduce separate
   424 definitions for the list comprehensions in question.\<close>
   424 definitions for the list comprehensions in question.\<close>
   436 syntax (ASCII)
   436 syntax (ASCII)
   437   "_lc_gen" :: "'a \<Rightarrow> 'a list \<Rightarrow> lc_qual"  ("_ <- _")
   437   "_lc_gen" :: "'a \<Rightarrow> 'a list \<Rightarrow> lc_qual"  ("_ <- _")
   438 
   438 
   439 parse_translation \<open>
   439 parse_translation \<open>
   440 let
   440 let
   441   val NilC = Syntax.const @{const_syntax Nil};
   441   val NilC = Syntax.const \<^const_syntax>\<open>Nil\<close>;
   442   val ConsC = Syntax.const @{const_syntax Cons};
   442   val ConsC = Syntax.const \<^const_syntax>\<open>Cons\<close>;
   443   val mapC = Syntax.const @{const_syntax map};
   443   val mapC = Syntax.const \<^const_syntax>\<open>map\<close>;
   444   val concatC = Syntax.const @{const_syntax concat};
   444   val concatC = Syntax.const \<^const_syntax>\<open>concat\<close>;
   445   val IfC = Syntax.const @{const_syntax If};
   445   val IfC = Syntax.const \<^const_syntax>\<open>If\<close>;
   446   val dummyC = Syntax.const @{const_syntax Pure.dummy_pattern}
   446   val dummyC = Syntax.const \<^const_syntax>\<open>Pure.dummy_pattern\<close>
   447 
   447 
   448   fun single x = ConsC $ x $ NilC;
   448   fun single x = ConsC $ x $ NilC;
   449 
   449 
   450   fun pat_tr ctxt p e opti = (* %x. case x of p => e | _ => [] *)
   450   fun pat_tr ctxt p e opti = (* %x. case x of p => e | _ => [] *)
   451     let
   451     let
   452       (* FIXME proper name context!? *)
   452       (* FIXME proper name context!? *)
   453       val x =
   453       val x =
   454         Free (singleton (Name.variant_list (fold Term.add_free_names [p, e] [])) "x", dummyT);
   454         Free (singleton (Name.variant_list (fold Term.add_free_names [p, e] [])) "x", dummyT);
   455       val e = if opti then single e else e;
   455       val e = if opti then single e else e;
   456       val case1 = Syntax.const @{syntax_const "_case1"} $ p $ e;
   456       val case1 = Syntax.const \<^syntax_const>\<open>_case1\<close> $ p $ e;
   457       val case2 =
   457       val case2 =
   458         Syntax.const @{syntax_const "_case1"} $ dummyC $ NilC;
   458         Syntax.const \<^syntax_const>\<open>_case1\<close> $ dummyC $ NilC;
   459       val cs = Syntax.const @{syntax_const "_case2"} $ case1 $ case2;
   459       val cs = Syntax.const \<^syntax_const>\<open>_case2\<close> $ case1 $ case2;
   460     in Syntax_Trans.abs_tr [x, Case_Translation.case_tr false ctxt [x, cs]] end;
   460     in Syntax_Trans.abs_tr [x, Case_Translation.case_tr false ctxt [x, cs]] end;
   461 
   461 
   462   fun pair_pat_tr (x as Free _) e = Syntax_Trans.abs_tr [x, e]
   462   fun pair_pat_tr (x as Free _) e = Syntax_Trans.abs_tr [x, e]
   463     | pair_pat_tr (_ $ p1 $ p2) e =
   463     | pair_pat_tr (_ $ p1 $ p2) e =
   464         Syntax.const @{const_syntax case_prod} $ pair_pat_tr p1 (pair_pat_tr p2 e)
   464         Syntax.const \<^const_syntax>\<open>case_prod\<close> $ pair_pat_tr p1 (pair_pat_tr p2 e)
   465     | pair_pat_tr dummy e = Syntax_Trans.abs_tr [Syntax.const "_idtdummy", e]
   465     | pair_pat_tr dummy e = Syntax_Trans.abs_tr [Syntax.const "_idtdummy", e]
   466 
   466 
   467   fun pair_pat ctxt (Const (@{const_syntax "Pair"},_) $ s $ t) =
   467   fun pair_pat ctxt (Const (\<^const_syntax>\<open>Pair\<close>,_) $ s $ t) =
   468         pair_pat ctxt s andalso pair_pat ctxt t
   468         pair_pat ctxt s andalso pair_pat ctxt t
   469     | pair_pat ctxt (Free (s,_)) =
   469     | pair_pat ctxt (Free (s,_)) =
   470         let
   470         let
   471           val thy = Proof_Context.theory_of ctxt;
   471           val thy = Proof_Context.theory_of ctxt;
   472           val s' = Proof_Context.intern_const ctxt s;
   472           val s' = Proof_Context.intern_const ctxt s;
   478     in if pair_pat ctxt p
   478     in if pair_pat ctxt p
   479        then (pair_pat_tr p e, true)
   479        then (pair_pat_tr p e, true)
   480        else (pat_tr ctxt p e opti, false)
   480        else (pat_tr ctxt p e opti, false)
   481     end
   481     end
   482 
   482 
   483   fun lc_tr ctxt [e, Const (@{syntax_const "_lc_test"}, _) $ b, qs] =
   483   fun lc_tr ctxt [e, Const (\<^syntax_const>\<open>_lc_test\<close>, _) $ b, qs] =
   484     let
   484     let
   485       val res =
   485       val res =
   486         (case qs of
   486         (case qs of
   487            Const (@{syntax_const "_lc_end"}, _) => single e
   487            Const (\<^syntax_const>\<open>_lc_end\<close>, _) => single e
   488          | Const (@{syntax_const "_lc_quals"}, _) $ q $ qs => lc_tr ctxt [e, q, qs]);
   488          | Const (\<^syntax_const>\<open>_lc_quals\<close>, _) $ q $ qs => lc_tr ctxt [e, q, qs]);
   489     in IfC $ b $ res $ NilC end
   489     in IfC $ b $ res $ NilC end
   490   | lc_tr ctxt
   490   | lc_tr ctxt
   491       [e, Const (@{syntax_const "_lc_gen"}, _) $ p $ es,
   491       [e, Const (\<^syntax_const>\<open>_lc_gen\<close>, _) $ p $ es,
   492           Const(@{syntax_const "_lc_end"}, _)] =
   492           Const(\<^syntax_const>\<open>_lc_end\<close>, _)] =
   493       (case abs_tr ctxt p e true of
   493       (case abs_tr ctxt p e true of
   494          (f, true) => mapC $ f $ es
   494          (f, true) => mapC $ f $ es
   495        | (f, false) => concatC $ (mapC $ f $ es))
   495        | (f, false) => concatC $ (mapC $ f $ es))
   496   | lc_tr ctxt
   496   | lc_tr ctxt
   497       [e, Const (@{syntax_const "_lc_gen"}, _) $ p $ es,
   497       [e, Const (\<^syntax_const>\<open>_lc_gen\<close>, _) $ p $ es,
   498           Const (@{syntax_const "_lc_quals"}, _) $ q $ qs] =
   498           Const (\<^syntax_const>\<open>_lc_quals\<close>, _) $ q $ qs] =
   499       let val e' = lc_tr ctxt [e, q, qs];
   499       let val e' = lc_tr ctxt [e, q, qs];
   500       in concatC $ (mapC $ (fst (abs_tr ctxt p e' false)) $ es) end;
   500       in concatC $ (mapC $ (fst (abs_tr ctxt p e' false)) $ es) end;
   501 
   501 
   502 in [(@{syntax_const "_listcompr"}, lc_tr)] end
   502 in [(\<^syntax_const>\<open>_listcompr\<close>, lc_tr)] end
   503 \<close>
   503 \<close>
   504 
   504 
   505 ML_val \<open>
   505 ML_val \<open>
   506   let
   506   let
   507     val read = Syntax.read_term @{context} o Syntax.implode_input;
   507     val read = Syntax.read_term \<^context> o Syntax.implode_input;
   508     fun check s1 s2 =
   508     fun check s1 s2 =
   509       read s1 aconv read s2 orelse
   509       read s1 aconv read s2 orelse
   510         error ("Check failed: " ^
   510         error ("Check failed: " ^
   511           quote (#1 (Input.source_content s1)) ^ Position.here_list [Input.pos_of s1, Input.pos_of s2]);
   511           quote (#1 (Input.source_content s1)) ^ Position.here_list [Input.pos_of s1, Input.pos_of s2]);
   512   in
   512   in
   553 
   553 
   554 (* conversion *)
   554 (* conversion *)
   555 
   555 
   556 fun all_exists_conv cv ctxt ct =
   556 fun all_exists_conv cv ctxt ct =
   557   (case Thm.term_of ct of
   557   (case Thm.term_of ct of
   558     Const (@{const_name Ex}, _) $ Abs _ =>
   558     Const (\<^const_name>\<open>Ex\<close>, _) $ Abs _ =>
   559       Conv.arg_conv (Conv.abs_conv (all_exists_conv cv o #2) ctxt) ct
   559       Conv.arg_conv (Conv.abs_conv (all_exists_conv cv o #2) ctxt) ct
   560   | _ => cv ctxt ct)
   560   | _ => cv ctxt ct)
   561 
   561 
   562 fun all_but_last_exists_conv cv ctxt ct =
   562 fun all_but_last_exists_conv cv ctxt ct =
   563   (case Thm.term_of ct of
   563   (case Thm.term_of ct of
   564     Const (@{const_name Ex}, _) $ Abs (_, _, Const (@{const_name Ex}, _) $ _) =>
   564     Const (\<^const_name>\<open>Ex\<close>, _) $ Abs (_, _, Const (\<^const_name>\<open>Ex\<close>, _) $ _) =>
   565       Conv.arg_conv (Conv.abs_conv (all_but_last_exists_conv cv o #2) ctxt) ct
   565       Conv.arg_conv (Conv.abs_conv (all_but_last_exists_conv cv o #2) ctxt) ct
   566   | _ => cv ctxt ct)
   566   | _ => cv ctxt ct)
   567 
   567 
   568 fun Collect_conv cv ctxt ct =
   568 fun Collect_conv cv ctxt ct =
   569   (case Thm.term_of ct of
   569   (case Thm.term_of ct of
   570     Const (@{const_name Collect}, _) $ Abs _ => Conv.arg_conv (Conv.abs_conv cv ctxt) ct
   570     Const (\<^const_name>\<open>Collect\<close>, _) $ Abs _ => Conv.arg_conv (Conv.abs_conv cv ctxt) ct
   571   | _ => raise CTERM ("Collect_conv", [ct]))
   571   | _ => raise CTERM ("Collect_conv", [ct]))
   572 
   572 
   573 fun rewr_conv' th = Conv.rewr_conv (mk_meta_eq th)
   573 fun rewr_conv' th = Conv.rewr_conv (mk_meta_eq th)
   574 
   574 
   575 fun conjunct_assoc_conv ct =
   575 fun conjunct_assoc_conv ct =
   590 val set_Nil_I = @{lemma "set [] = {x. False}" by (simp add: empty_def [symmetric])}
   590 val set_Nil_I = @{lemma "set [] = {x. False}" by (simp add: empty_def [symmetric])}
   591 val set_singleton = @{lemma "set [a] = {x. x = a}" by simp}
   591 val set_singleton = @{lemma "set [a] = {x. x = a}" by simp}
   592 val inst_Collect_mem_eq = @{lemma "set A = {x. x \<in> set A}" by simp}
   592 val inst_Collect_mem_eq = @{lemma "set A = {x. x \<in> set A}" by simp}
   593 val del_refl_eq = @{lemma "(t = t \<and> P) \<equiv> P" by simp}
   593 val del_refl_eq = @{lemma "(t = t \<and> P) \<equiv> P" by simp}
   594 
   594 
   595 fun mk_set T = Const (@{const_name set}, HOLogic.listT T --> HOLogic.mk_setT T)
   595 fun mk_set T = Const (\<^const_name>\<open>set\<close>, HOLogic.listT T --> HOLogic.mk_setT T)
   596 fun dest_set (Const (@{const_name set}, _) $ xs) = xs
   596 fun dest_set (Const (\<^const_name>\<open>set\<close>, _) $ xs) = xs
   597 
   597 
   598 fun dest_singleton_list (Const (@{const_name Cons}, _) $ t $ (Const (@{const_name Nil}, _))) = t
   598 fun dest_singleton_list (Const (\<^const_name>\<open>Cons\<close>, _) $ t $ (Const (\<^const_name>\<open>Nil\<close>, _))) = t
   599   | dest_singleton_list t = raise TERM ("dest_singleton_list", [t])
   599   | dest_singleton_list t = raise TERM ("dest_singleton_list", [t])
   600 
   600 
   601 (*We check that one case returns a singleton list and all other cases
   601 (*We check that one case returns a singleton list and all other cases
   602   return [], and return the index of the one singleton list case.*)
   602   return [], and return the index of the one singleton list case.*)
   603 fun possible_index_of_singleton_case cases =
   603 fun possible_index_of_singleton_case cases =
   604   let
   604   let
   605     fun check (i, case_t) s =
   605     fun check (i, case_t) s =
   606       (case strip_abs_body case_t of
   606       (case strip_abs_body case_t of
   607         (Const (@{const_name Nil}, _)) => s
   607         (Const (\<^const_name>\<open>Nil\<close>, _)) => s
   608       | _ => (case s of SOME NONE => SOME (SOME i) | _ => NONE))
   608       | _ => (case s of SOME NONE => SOME (SOME i) | _ => NONE))
   609   in
   609   in
   610     fold_index check cases (SOME NONE) |> the_default NONE
   610     fold_index check cases (SOME NONE) |> the_default NONE
   611   end
   611   end
   612 
   612 
   613 (*returns condition continuing term option*)
   613 (*returns condition continuing term option*)
   614 fun dest_if (Const (@{const_name If}, _) $ cond $ then_t $ Const (@{const_name Nil}, _)) =
   614 fun dest_if (Const (\<^const_name>\<open>If\<close>, _) $ cond $ then_t $ Const (\<^const_name>\<open>Nil\<close>, _)) =
   615       SOME (cond, then_t)
   615       SOME (cond, then_t)
   616   | dest_if _ = NONE
   616   | dest_if _ = NONE
   617 
   617 
   618 (*returns (case_expr type index chosen_case constr_name) option*)
   618 (*returns (case_expr type index chosen_case constr_name) option*)
   619 fun dest_case ctxt case_term =
   619 fun dest_case ctxt case_term =
   715             val x' = incr_boundvars (length vs) x
   715             val x' = incr_boundvars (length vs) x
   716             val eqs' = map (incr_boundvars (length vs)) eqs
   716             val eqs' = map (incr_boundvars (length vs)) eqs
   717             val constr_t =
   717             val constr_t =
   718               list_comb
   718               list_comb
   719                 (Const (constr_name, map snd vs ---> T), map Bound (((length vs) - 1) downto 0))
   719                 (Const (constr_name, map snd vs ---> T), map Bound (((length vs) - 1) downto 0))
   720             val constr_eq = Const (@{const_name HOL.eq}, T --> T --> @{typ bool}) $ constr_t $ x'
   720             val constr_eq = Const (\<^const_name>\<open>HOL.eq\<close>, T --> T --> \<^typ>\<open>bool\<close>) $ constr_t $ x'
   721           in
   721           in
   722             make_inner_eqs (rev vs @ bound_vs) (Case (T, i) :: Tis) (constr_eq :: eqs') body
   722             make_inner_eqs (rev vs @ bound_vs) (Case (T, i) :: Tis) (constr_eq :: eqs') body
   723           end
   723           end
   724       | NONE =>
   724       | NONE =>
   725           (case dest_if t of
   725           (case dest_if t of
   726             SOME (condition, cont) => make_inner_eqs bound_vs (If :: Tis) (condition :: eqs) cont
   726             SOME (condition, cont) => make_inner_eqs bound_vs (If :: Tis) (condition :: eqs) cont
   727           | NONE =>
   727           | NONE =>
   728             if null eqs then NONE (*no rewriting, nothing to be done*)
   728             if null eqs then NONE (*no rewriting, nothing to be done*)
   729             else
   729             else
   730               let
   730               let
   731                 val Type (@{type_name list}, [rT]) = fastype_of1 (map snd bound_vs, t)
   731                 val Type (\<^type_name>\<open>list\<close>, [rT]) = fastype_of1 (map snd bound_vs, t)
   732                 val pat_eq =
   732                 val pat_eq =
   733                   (case try dest_singleton_list t of
   733                   (case try dest_singleton_list t of
   734                     SOME t' =>
   734                     SOME t' =>
   735                       Const (@{const_name HOL.eq}, rT --> rT --> @{typ bool}) $
   735                       Const (\<^const_name>\<open>HOL.eq\<close>, rT --> rT --> \<^typ>\<open>bool\<close>) $
   736                         Bound (length bound_vs) $ t'
   736                         Bound (length bound_vs) $ t'
   737                   | NONE =>
   737                   | NONE =>
   738                       Const (@{const_name Set.member}, rT --> HOLogic.mk_setT rT --> @{typ bool}) $
   738                       Const (\<^const_name>\<open>Set.member\<close>, rT --> HOLogic.mk_setT rT --> \<^typ>\<open>bool\<close>) $
   739                         Bound (length bound_vs) $ (mk_set rT $ t))
   739                         Bound (length bound_vs) $ (mk_set rT $ t))
   740                 val reverse_bounds = curry subst_bounds
   740                 val reverse_bounds = curry subst_bounds
   741                   ((map Bound ((length bound_vs - 1) downto 0)) @ [Bound (length bound_vs)])
   741                   ((map Bound ((length bound_vs - 1) downto 0)) @ [Bound (length bound_vs)])
   742                 val eqs' = map reverse_bounds eqs
   742                 val eqs' = map reverse_bounds eqs
   743                 val pat_eq' = reverse_bounds pat_eq
   743                 val pat_eq' = reverse_bounds pat_eq
   766 
   766 
   767 code_datatype set coset
   767 code_datatype set coset
   768 hide_const (open) coset
   768 hide_const (open) coset
   769 
   769 
   770 
   770 
   771 subsubsection \<open>@{const Nil} and @{const Cons}\<close>
   771 subsubsection \<open>\<^const>\<open>Nil\<close> and \<^const>\<open>Cons\<close>\<close>
   772 
   772 
   773 lemma not_Cons_self [simp]:
   773 lemma not_Cons_self [simp]:
   774   "xs \<noteq> x # xs"
   774   "xs \<noteq> x # xs"
   775 by (induct xs) auto
   775 by (induct xs) auto
   776 
   776 
   802   by (auto intro!: inj_onI)
   802   by (auto intro!: inj_onI)
   803 
   803 
   804 lemma inj_on_Cons1 [simp]: "inj_on ((#) x) A"
   804 lemma inj_on_Cons1 [simp]: "inj_on ((#) x) A"
   805 by(simp add: inj_on_def)
   805 by(simp add: inj_on_def)
   806 
   806 
   807 subsubsection \<open>@{const length}\<close>
   807 subsubsection \<open>\<^const>\<open>length\<close>\<close>
   808 
   808 
   809 text \<open>
   809 text \<open>
   810   Needs to come before \<open>@\<close> because of theorem \<open>append_eq_append_conv\<close>.
   810   Needs to come before \<open>@\<close> because of theorem \<open>append_eq_append_conv\<close>.
   811 \<close>
   811 \<close>
   812 
   812 
   898 of those of the other list and there are fewer Cons's in one than the other.
   898 of those of the other list and there are fewer Cons's in one than the other.
   899 *)
   899 *)
   900 
   900 
   901 let
   901 let
   902 
   902 
   903 fun len (Const(@{const_name Nil},_)) acc = acc
   903 fun len (Const(\<^const_name>\<open>Nil\<close>,_)) acc = acc
   904   | len (Const(@{const_name Cons},_) $ _ $ xs) (ts,n) = len xs (ts,n+1)
   904   | len (Const(\<^const_name>\<open>Cons\<close>,_) $ _ $ xs) (ts,n) = len xs (ts,n+1)
   905   | len (Const(@{const_name append},_) $ xs $ ys) acc = len xs (len ys acc)
   905   | len (Const(\<^const_name>\<open>append\<close>,_) $ xs $ ys) acc = len xs (len ys acc)
   906   | len (Const(@{const_name rev},_) $ xs) acc = len xs acc
   906   | len (Const(\<^const_name>\<open>rev\<close>,_) $ xs) acc = len xs acc
   907   | len (Const(@{const_name map},_) $ _ $ xs) acc = len xs acc
   907   | len (Const(\<^const_name>\<open>map\<close>,_) $ _ $ xs) acc = len xs acc
   908   | len t (ts,n) = (t::ts,n);
   908   | len t (ts,n) = (t::ts,n);
   909 
   909 
   910 val ss = simpset_of @{context};
   910 val ss = simpset_of \<^context>;
   911 
   911 
   912 fun list_neq ctxt ct =
   912 fun list_neq ctxt ct =
   913   let
   913   let
   914     val (Const(_,eqT) $ lhs $ rhs) = Thm.term_of ct;
   914     val (Const(_,eqT) $ lhs $ rhs) = Thm.term_of ct;
   915     val (ls,m) = len lhs ([],0) and (rs,n) = len rhs ([],0);
   915     val (ls,m) = len lhs ([],0) and (rs,n) = len rhs ([],0);
  1040 - or both lists end in the same list.
  1040 - or both lists end in the same list.
  1041 \<close>
  1041 \<close>
  1042 
  1042 
  1043 simproc_setup list_eq ("(xs::'a list) = ys")  = \<open>
  1043 simproc_setup list_eq ("(xs::'a list) = ys")  = \<open>
  1044   let
  1044   let
  1045     fun last (cons as Const (@{const_name Cons}, _) $ _ $ xs) =
  1045     fun last (cons as Const (\<^const_name>\<open>Cons\<close>, _) $ _ $ xs) =
  1046           (case xs of Const (@{const_name Nil}, _) => cons | _ => last xs)
  1046           (case xs of Const (\<^const_name>\<open>Nil\<close>, _) => cons | _ => last xs)
  1047       | last (Const(@{const_name append},_) $ _ $ ys) = last ys
  1047       | last (Const(\<^const_name>\<open>append\<close>,_) $ _ $ ys) = last ys
  1048       | last t = t;
  1048       | last t = t;
  1049 
  1049 
  1050     fun list1 (Const(@{const_name Cons},_) $ _ $ Const(@{const_name Nil},_)) = true
  1050     fun list1 (Const(\<^const_name>\<open>Cons\<close>,_) $ _ $ Const(\<^const_name>\<open>Nil\<close>,_)) = true
  1051       | list1 _ = false;
  1051       | list1 _ = false;
  1052 
  1052 
  1053     fun butlast ((cons as Const(@{const_name Cons},_) $ x) $ xs) =
  1053     fun butlast ((cons as Const(\<^const_name>\<open>Cons\<close>,_) $ x) $ xs) =
  1054           (case xs of Const (@{const_name Nil}, _) => xs | _ => cons $ butlast xs)
  1054           (case xs of Const (\<^const_name>\<open>Nil\<close>, _) => xs | _ => cons $ butlast xs)
  1055       | butlast ((app as Const (@{const_name append}, _) $ xs) $ ys) = app $ butlast ys
  1055       | butlast ((app as Const (\<^const_name>\<open>append\<close>, _) $ xs) $ ys) = app $ butlast ys
  1056       | butlast xs = Const(@{const_name Nil}, fastype_of xs);
  1056       | butlast xs = Const(\<^const_name>\<open>Nil\<close>, fastype_of xs);
  1057 
  1057 
  1058     val rearr_ss =
  1058     val rearr_ss =
  1059       simpset_of (put_simpset HOL_basic_ss @{context}
  1059       simpset_of (put_simpset HOL_basic_ss \<^context>
  1060         addsimps [@{thm append_assoc}, @{thm append_Nil}, @{thm append_Cons}]);
  1060         addsimps [@{thm append_assoc}, @{thm append_Nil}, @{thm append_Cons}]);
  1061 
  1061 
  1062     fun list_eq ctxt (F as (eq as Const(_,eqT)) $ lhs $ rhs) =
  1062     fun list_eq ctxt (F as (eq as Const(_,eqT)) $ lhs $ rhs) =
  1063       let
  1063       let
  1064         val lastl = last lhs and lastr = last rhs;
  1064         val lastl = last lhs and lastr = last rhs;
  1065         fun rearr conv =
  1065         fun rearr conv =
  1066           let
  1066           let
  1067             val lhs1 = butlast lhs and rhs1 = butlast rhs;
  1067             val lhs1 = butlast lhs and rhs1 = butlast rhs;
  1068             val Type(_,listT::_) = eqT
  1068             val Type(_,listT::_) = eqT
  1069             val appT = [listT,listT] ---> listT
  1069             val appT = [listT,listT] ---> listT
  1070             val app = Const(@{const_name append},appT)
  1070             val app = Const(\<^const_name>\<open>append\<close>,appT)
  1071             val F2 = eq $ (app$lhs1$lastl) $ (app$rhs1$lastr)
  1071             val F2 = eq $ (app$lhs1$lastl) $ (app$rhs1$lastr)
  1072             val eq = HOLogic.mk_Trueprop (HOLogic.mk_eq (F,F2));
  1072             val eq = HOLogic.mk_Trueprop (HOLogic.mk_eq (F,F2));
  1073             val thm = Goal.prove ctxt [] [] eq
  1073             val thm = Goal.prove ctxt [] [] eq
  1074               (K (simp_tac (put_simpset rearr_ss ctxt) 1));
  1074               (K (simp_tac (put_simpset rearr_ss ctxt) 1));
  1075           in SOME ((conv RS (thm RS trans)) RS eq_reflection) end;
  1075           in SOME ((conv RS (thm RS trans)) RS eq_reflection) end;
  1080       end;
  1080       end;
  1081   in fn _ => fn ctxt => fn ct => list_eq ctxt (Thm.term_of ct) end
  1081   in fn _ => fn ctxt => fn ct => list_eq ctxt (Thm.term_of ct) end
  1082 \<close>
  1082 \<close>
  1083 
  1083 
  1084 
  1084 
  1085 subsubsection \<open>@{const map}\<close>
  1085 subsubsection \<open>\<^const>\<open>map\<close>\<close>
  1086 
  1086 
  1087 lemma hd_map: "xs \<noteq> [] \<Longrightarrow> hd (map f xs) = f (hd xs)"
  1087 lemma hd_map: "xs \<noteq> [] \<Longrightarrow> hd (map f xs) = f (hd xs)"
  1088 by (cases xs) simp_all
  1088 by (cases xs) simp_all
  1089 
  1089 
  1090 lemma map_tl: "map f (tl xs) = tl (map f xs)"
  1090 lemma map_tl: "map f (tl xs) = tl (map f xs)"
  1212 by (simp_all add: id_def)
  1212 by (simp_all add: id_def)
  1213 
  1213 
  1214 declare map.id [simp]
  1214 declare map.id [simp]
  1215 
  1215 
  1216 
  1216 
  1217 subsubsection \<open>@{const rev}\<close>
  1217 subsubsection \<open>\<^const>\<open>rev\<close>\<close>
  1218 
  1218 
  1219 lemma rev_append [simp]: "rev (xs @ ys) = rev ys @ rev xs"
  1219 lemma rev_append [simp]: "rev (xs @ ys) = rev ys @ rev xs"
  1220 by (induct xs) auto
  1220 by (induct xs) auto
  1221 
  1221 
  1222 lemma rev_rev_ident [simp]: "rev (rev xs) = xs"
  1222 lemma rev_rev_ident [simp]: "rev (rev xs) = xs"
  1275 
  1275 
  1276 lemma rev_eq_Cons_iff[iff]: "(rev xs = y#ys) = (xs = rev ys @ [y])"
  1276 lemma rev_eq_Cons_iff[iff]: "(rev xs = y#ys) = (xs = rev ys @ [y])"
  1277 by(rule rev_cases[of xs]) auto
  1277 by(rule rev_cases[of xs]) auto
  1278 
  1278 
  1279 
  1279 
  1280 subsubsection \<open>@{const set}\<close>
  1280 subsubsection \<open>\<^const>\<open>set\<close>\<close>
  1281 
  1281 
  1282 declare list.set[code_post]  \<comment> \<open>pretty output\<close>
  1282 declare list.set[code_post]  \<comment> \<open>pretty output\<close>
  1283 
  1283 
  1284 lemma finite_set [iff]: "finite (set xs)"
  1284 lemma finite_set [iff]: "finite (set xs)"
  1285 by (induct xs) auto
  1285 by (induct xs) auto
  1443   "\<lbrakk> x \<notin> set xs; x \<notin> set ys \<rbrakk> \<Longrightarrow>
  1443   "\<lbrakk> x \<notin> set xs; x \<notin> set ys \<rbrakk> \<Longrightarrow>
  1444    xs @ x # ys = xs' @ x # ys' \<longleftrightarrow> (xs = xs' \<and> ys = ys')"
  1444    xs @ x # ys = xs' @ x # ys' \<longleftrightarrow> (xs = xs' \<and> ys = ys')"
  1445 by(auto simp: append_eq_Cons_conv Cons_eq_append_conv append_eq_append_conv2)
  1445 by(auto simp: append_eq_Cons_conv Cons_eq_append_conv append_eq_append_conv2)
  1446 
  1446 
  1447 
  1447 
  1448 subsubsection \<open>@{const filter}\<close>
  1448 subsubsection \<open>\<^const>\<open>filter\<close>\<close>
  1449 
  1449 
  1450 lemma filter_append [simp]: "filter P (xs @ ys) = filter P xs @ filter P ys"
  1450 lemma filter_append [simp]: "filter P (xs @ ys) = filter P xs @ filter P ys"
  1451 by (induct xs) auto
  1451 by (induct xs) auto
  1452 
  1452 
  1453 lemma rev_filter: "rev (filter P xs) = filter P (rev xs)"
  1453 lemma rev_filter: "rev (filter P xs) = filter P (rev xs)"
  1624   unfolding partition_filter1[symmetric] by simp
  1624   unfolding partition_filter1[symmetric] by simp
  1625 
  1625 
  1626 declare partition.simps[simp del]
  1626 declare partition.simps[simp del]
  1627 
  1627 
  1628 
  1628 
  1629 subsubsection \<open>@{const concat}\<close>
  1629 subsubsection \<open>\<^const>\<open>concat\<close>\<close>
  1630 
  1630 
  1631 lemma concat_append [simp]: "concat (xs @ ys) = concat xs @ concat ys"
  1631 lemma concat_append [simp]: "concat (xs @ ys) = concat xs @ concat ys"
  1632   by (induct xs) auto
  1632   by (induct xs) auto
  1633 
  1633 
  1634 lemma concat_eq_Nil_conv [simp]: "(concat xss = []) = (\<forall>xs \<in> set xss. xs = [])"
  1634 lemma concat_eq_Nil_conv [simp]: "(concat xss = []) = (\<forall>xs \<in> set xss. xs = [])"
  1660 
  1660 
  1661 lemma concat_injective: "concat xs = concat ys ==> length xs = length ys ==> \<forall>(x, y) \<in> set (zip xs ys). length x = length y ==> xs = ys"
  1661 lemma concat_injective: "concat xs = concat ys ==> length xs = length ys ==> \<forall>(x, y) \<in> set (zip xs ys). length x = length y ==> xs = ys"
  1662   by (simp add: concat_eq_concat_iff)
  1662   by (simp add: concat_eq_concat_iff)
  1663 
  1663 
  1664 
  1664 
  1665 subsubsection \<open>@{const nth}\<close>
  1665 subsubsection \<open>\<^const>\<open>nth\<close>\<close>
  1666 
  1666 
  1667 lemma nth_Cons_0 [simp, code]: "(x # xs)!0 = x"
  1667 lemma nth_Cons_0 [simp, code]: "(x # xs)!0 = x"
  1668   by auto
  1668   by auto
  1669 
  1669 
  1670 lemma nth_Cons_Suc [simp, code]: "(x # xs)!(Suc n) = xs!n"
  1670 lemma nth_Cons_Suc [simp, code]: "(x # xs)!(Suc n) = xs!n"
  1812     thus "?R" ..
  1812     thus "?R" ..
  1813   qed
  1813   qed
  1814 qed
  1814 qed
  1815 
  1815 
  1816 
  1816 
  1817 subsubsection \<open>@{const list_update}\<close>
  1817 subsubsection \<open>\<^const>\<open>list_update\<close>\<close>
  1818 
  1818 
  1819 lemma length_list_update [simp]: "length(xs[i:=x]) = length xs"
  1819 lemma length_list_update [simp]: "length(xs[i:=x]) = length xs"
  1820   by (induct xs arbitrary: i) (auto split: nat.split)
  1820   by (induct xs arbitrary: i) (auto split: nat.split)
  1821 
  1821 
  1822 lemma nth_list_update:
  1822 lemma nth_list_update:
  1892   "(x # xs)[0 := y] = y # xs"
  1892   "(x # xs)[0 := y] = y # xs"
  1893   "(x # xs)[Suc i := y] = x # xs[i := y]"
  1893   "(x # xs)[Suc i := y] = x # xs[i := y]"
  1894   by simp_all
  1894   by simp_all
  1895 
  1895 
  1896 
  1896 
  1897 subsubsection \<open>@{const last} and @{const butlast}\<close>
  1897 subsubsection \<open>\<^const>\<open>last\<close> and \<^const>\<open>butlast\<close>\<close>
  1898 
  1898 
  1899 lemma last_snoc [simp]: "last (xs @ [x]) = x"
  1899 lemma last_snoc [simp]: "last (xs @ [x]) = x"
  1900   by (induct xs) auto
  1900   by (induct xs) auto
  1901 
  1901 
  1902 lemma butlast_snoc [simp]: "butlast (xs @ [x]) = xs"
  1902 lemma butlast_snoc [simp]: "butlast (xs @ [x]) = xs"
  1992        \<and> (xs' = [] \<or> ys' = [] \<or> last xs' \<noteq> last ys')"
  1992        \<and> (xs' = [] \<or> ys' = [] \<or> last xs' \<noteq> last ys')"
  1993   using longest_common_prefix[of "rev xs" "rev ys"]
  1993   using longest_common_prefix[of "rev xs" "rev ys"]
  1994   unfolding rev_swap rev_append by (metis last_rev rev_is_Nil_conv)
  1994   unfolding rev_swap rev_append by (metis last_rev rev_is_Nil_conv)
  1995 
  1995 
  1996 
  1996 
  1997 subsubsection \<open>@{const take} and @{const drop}\<close>
  1997 subsubsection \<open>\<^const>\<open>take\<close> and \<^const>\<open>drop\<close>\<close>
  1998 
  1998 
  1999 lemma take_0: "take 0 xs = []"
  1999 lemma take_0: "take 0 xs = []"
  2000   by (induct xs) auto
  2000   by (induct xs) auto
  2001 
  2001 
  2002 lemma drop_0: "drop 0 xs = xs"
  2002 lemma drop_0: "drop 0 xs = xs"
  2265 
  2265 
  2266 lemma nth_image: "l \<le> size xs \<Longrightarrow> nth xs ` {0..<l} = set(take l xs)"
  2266 lemma nth_image: "l \<le> size xs \<Longrightarrow> nth xs ` {0..<l} = set(take l xs)"
  2267   by(auto simp: set_conv_nth image_def) (metis Suc_le_eq nth_take order_trans)
  2267   by(auto simp: set_conv_nth image_def) (metis Suc_le_eq nth_take order_trans)
  2268 
  2268 
  2269 
  2269 
  2270 subsubsection \<open>@{const takeWhile} and @{const dropWhile}\<close>
  2270 subsubsection \<open>\<^const>\<open>takeWhile\<close> and \<^const>\<open>dropWhile\<close>\<close>
  2271 
  2271 
  2272 lemma length_takeWhile_le: "length (takeWhile P xs) \<le> length xs"
  2272 lemma length_takeWhile_le: "length (takeWhile P xs) \<le> length xs"
  2273   by (induct xs) auto
  2273   by (induct xs) auto
  2274 
  2274 
  2275 lemma takeWhile_dropWhile_id [simp]: "takeWhile P xs @ dropWhile P xs = xs"
  2275 lemma takeWhile_dropWhile_id [simp]: "takeWhile P xs @ dropWhile P xs = xs"
  2439 lemma dropWhile_idem [simp]:
  2439 lemma dropWhile_idem [simp]:
  2440   "dropWhile P (dropWhile P xs) = dropWhile P xs"
  2440   "dropWhile P (dropWhile P xs) = dropWhile P xs"
  2441   by (induct xs) auto
  2441   by (induct xs) auto
  2442 
  2442 
  2443 
  2443 
  2444 subsubsection \<open>@{const zip}\<close>
  2444 subsubsection \<open>\<^const>\<open>zip\<close>\<close>
  2445 
  2445 
  2446 lemma zip_Nil [simp]: "zip [] ys = []"
  2446 lemma zip_Nil [simp]: "zip [] ys = []"
  2447   by (induct ys) auto
  2447   by (induct ys) auto
  2448 
  2448 
  2449 lemma zip_Cons_Cons [simp]: "zip (x # xs) (y # ys) = (x, y) # zip xs ys"
  2449 lemma zip_Cons_Cons [simp]: "zip (x # xs) (y # ys) = (x, y) # zip xs ys"
  2633   from this assms show ?thesis
  2633   from this assms show ?thesis
  2634     by (induct xs ys rule: list_induct2) (simp_all add: prod_eqI)
  2634     by (induct xs ys rule: list_induct2) (simp_all add: prod_eqI)
  2635 qed
  2635 qed
  2636 
  2636 
  2637 
  2637 
  2638 subsubsection \<open>@{const list_all2}\<close>
  2638 subsubsection \<open>\<^const>\<open>list_all2\<close>\<close>
  2639 
  2639 
  2640 lemma list_all2_lengthD [intro?]:
  2640 lemma list_all2_lengthD [intro?]:
  2641   "list_all2 P xs ys ==> length xs = length ys"
  2641   "list_all2 P xs ys ==> length xs = length ys"
  2642   by (simp add: list_all2_iff)
  2642   by (simp add: list_all2_iff)
  2643 
  2643 
  2814   by(rule list_all2_all_nthI[where P="(=)", unfolded list.rel_eq]) simp_all
  2814   by(rule list_all2_all_nthI[where P="(=)", unfolded list.rel_eq]) simp_all
  2815 
  2815 
  2816 lemma zip_replicate2: "zip xs (replicate n y) = map (\<lambda>x. (x, y)) (take n xs)"
  2816 lemma zip_replicate2: "zip xs (replicate n y) = map (\<lambda>x. (x, y)) (take n xs)"
  2817   by(subst zip_commute)(simp add: zip_replicate1)
  2817   by(subst zip_commute)(simp add: zip_replicate1)
  2818 
  2818 
  2819 subsubsection \<open>@{const List.product} and @{const product_lists}\<close>
  2819 subsubsection \<open>\<^const>\<open>List.product\<close> and \<^const>\<open>product_lists\<close>\<close>
  2820 
  2820 
  2821 lemma product_concat_map:
  2821 lemma product_concat_map:
  2822   "List.product xs ys = concat (map (\<lambda>x. map (\<lambda>y. (x,y)) ys) xs)"
  2822   "List.product xs ys = concat (map (\<lambda>x. map (\<lambda>y. (x,y)) ys) xs)"
  2823   by(induction xs) (simp)+
  2823   by(induction xs) (simp)+
  2824 
  2824 
  2855   fix xs assume "?R xs"
  2855   fix xs assume "?R xs"
  2856   then show "xs \<in> ?L" by induct auto
  2856   then show "xs \<in> ?L" by induct auto
  2857 qed
  2857 qed
  2858 
  2858 
  2859 
  2859 
  2860 subsubsection \<open>@{const fold} with natural argument order\<close>
  2860 subsubsection \<open>\<^const>\<open>fold\<close> with natural argument order\<close>
  2861 
  2861 
  2862 lemma fold_simps [code]: \<comment> \<open>eta-expanded variant for generated code -- enables tail-recursion optimisation in Scala\<close>
  2862 lemma fold_simps [code]: \<comment> \<open>eta-expanded variant for generated code -- enables tail-recursion optimisation in Scala\<close>
  2863   "fold f [] s = s"
  2863   "fold f [] s = s"
  2864   "fold f (x # xs) s = fold f xs (f x s)"
  2864   "fold f (x # xs) s = fold f xs (f x s)"
  2865   by simp_all
  2865   by simp_all
  2917   by (simp add: fold_Cons_rev)
  2917   by (simp add: fold_Cons_rev)
  2918 
  2918 
  2919 lemma fold_append_concat_rev: "fold append xss = append (concat (rev xss))"
  2919 lemma fold_append_concat_rev: "fold append xss = append (concat (rev xss))"
  2920   by (induct xss) simp_all
  2920   by (induct xss) simp_all
  2921 
  2921 
  2922 text \<open>@{const Finite_Set.fold} and @{const fold}\<close>
  2922 text \<open>\<^const>\<open>Finite_Set.fold\<close> and \<^const>\<open>fold\<close>\<close>
  2923 
  2923 
  2924 lemma (in comp_fun_commute) fold_set_fold_remdups:
  2924 lemma (in comp_fun_commute) fold_set_fold_remdups:
  2925   "Finite_Set.fold f y (set xs) = fold f (remdups xs) y"
  2925   "Finite_Set.fold f y (set xs) = fold f (remdups xs) y"
  2926   by (rule sym, induct xs arbitrary: y) (simp_all add: fold_fun_left_comm insert_absorb)
  2926   by (rule sym, induct xs arbitrary: y) (simp_all add: fold_fun_left_comm insert_absorb)
  2927 
  2927 
  2995 lemma (in complete_lattice) SUP_set_fold:
  2995 lemma (in complete_lattice) SUP_set_fold:
  2996   "\<Squnion>(f ` set xs) = fold (sup \<circ> f) xs bot"
  2996   "\<Squnion>(f ` set xs) = fold (sup \<circ> f) xs bot"
  2997   using Sup_set_fold [of "map f xs"] by (simp add: fold_map)
  2997   using Sup_set_fold [of "map f xs"] by (simp add: fold_map)
  2998 
  2998 
  2999 
  2999 
  3000 subsubsection \<open>Fold variants: @{const foldr} and @{const foldl}\<close>
  3000 subsubsection \<open>Fold variants: \<^const>\<open>foldr\<close> and \<^const>\<open>foldl\<close>\<close>
  3001 
  3001 
  3002 text \<open>Correspondence\<close>
  3002 text \<open>Correspondence\<close>
  3003 
  3003 
  3004 lemma foldr_conv_fold [code_abbrev]: "foldr f xs = fold f (rev xs)"
  3004 lemma foldr_conv_fold [code_abbrev]: "foldr f xs = fold f (rev xs)"
  3005   by (induct xs) simp_all
  3005   by (induct xs) simp_all
  3048 lemma concat_conv_foldr [code]:
  3048 lemma concat_conv_foldr [code]:
  3049   "concat xss = foldr append xss []"
  3049   "concat xss = foldr append xss []"
  3050   by (simp add: fold_append_concat_rev foldr_conv_fold)
  3050   by (simp add: fold_append_concat_rev foldr_conv_fold)
  3051 
  3051 
  3052 
  3052 
  3053 subsubsection \<open>@{const upt}\<close>
  3053 subsubsection \<open>\<^const>\<open>upt\<close>\<close>
  3054 
  3054 
  3055 lemma upt_rec[code]: "[i..<j] = (if i<j then i#[Suc i..<j] else [])"
  3055 lemma upt_rec[code]: "[i..<j] = (if i<j then i#[Suc i..<j] else [])"
  3056   \<comment> \<open>simp does not terminate!\<close>
  3056   \<comment> \<open>simp does not terminate!\<close>
  3057   by (induct j) auto
  3057   by (induct j) auto
  3058 
  3058 
  3184 lemma nth_Cons_numeral [simp]:
  3184 lemma nth_Cons_numeral [simp]:
  3185   "(x # xs) ! numeral v = xs ! (numeral v - 1)"
  3185   "(x # xs) ! numeral v = xs ! (numeral v - 1)"
  3186 by (simp add: nth_Cons')
  3186 by (simp add: nth_Cons')
  3187 
  3187 
  3188 
  3188 
  3189 subsubsection \<open>\<open>upto\<close>: interval-list on @{typ int}\<close>
  3189 subsubsection \<open>\<open>upto\<close>: interval-list on \<^typ>\<open>int\<close>\<close>
  3190 
  3190 
  3191 function upto :: "int \<Rightarrow> int \<Rightarrow> int list" ("(1[_../_])") where
  3191 function upto :: "int \<Rightarrow> int \<Rightarrow> int list" ("(1[_../_])") where
  3192   "upto i j = (if i \<le> j then i # [i+1..j] else [])"
  3192   "upto i j = (if i \<le> j then i # [i+1..j] else [])"
  3193 by auto
  3193 by auto
  3194 termination
  3194 termination
  3268 
  3268 
  3269 lemma upto_code[code]: "[i..j] = upto_aux i j []"
  3269 lemma upto_code[code]: "[i..j] = upto_aux i j []"
  3270 by(simp add: upto_aux_def)
  3270 by(simp add: upto_aux_def)
  3271 
  3271 
  3272 
  3272 
  3273 subsubsection \<open>@{const distinct} and @{const remdups} and @{const remdups_adj}\<close>
  3273 subsubsection \<open>\<^const>\<open>distinct\<close> and \<^const>\<open>remdups\<close> and \<^const>\<open>remdups_adj\<close>\<close>
  3274 
  3274 
  3275 lemma distinct_tl: "distinct xs \<Longrightarrow> distinct (tl xs)"
  3275 lemma distinct_tl: "distinct xs \<Longrightarrow> distinct (tl xs)"
  3276 by (cases xs) simp_all
  3276 by (cases xs) simp_all
  3277 
  3277 
  3278 lemma distinct_append [simp]:
  3278 lemma distinct_append [simp]:
  3791     by (induct q) simp_all
  3791     by (induct q) simp_all
  3792   ultimately show ?thesis by simp
  3792   ultimately show ?thesis by simp
  3793 qed
  3793 qed
  3794 
  3794 
  3795 
  3795 
  3796 subsubsection \<open>@{const insert}\<close>
  3796 subsubsection \<open>\<^const>\<open>insert\<close>\<close>
  3797 
  3797 
  3798 lemma in_set_insert [simp]:
  3798 lemma in_set_insert [simp]:
  3799   "x \<in> set xs \<Longrightarrow> List.insert x xs = xs"
  3799   "x \<in> set xs \<Longrightarrow> List.insert x xs = xs"
  3800 by (simp add: List.insert_def)
  3800 by (simp add: List.insert_def)
  3801 
  3801 
  3815 lemma insert_remdups:
  3815 lemma insert_remdups:
  3816   "List.insert x (remdups xs) = remdups (List.insert x xs)"
  3816   "List.insert x (remdups xs) = remdups (List.insert x xs)"
  3817 by (simp add: List.insert_def)
  3817 by (simp add: List.insert_def)
  3818 
  3818 
  3819 
  3819 
  3820 subsubsection \<open>@{const List.union}\<close>
  3820 subsubsection \<open>\<^const>\<open>List.union\<close>\<close>
  3821 
  3821 
  3822 text\<open>This is all one should need to know about union:\<close>
  3822 text\<open>This is all one should need to know about union:\<close>
  3823 lemma set_union[simp]: "set (List.union xs ys) = set xs \<union> set ys"
  3823 lemma set_union[simp]: "set (List.union xs ys) = set xs \<union> set ys"
  3824 unfolding List.union_def
  3824 unfolding List.union_def
  3825 by(induct xs arbitrary: ys) simp_all
  3825 by(induct xs arbitrary: ys) simp_all
  3827 lemma distinct_union[simp]: "distinct(List.union xs ys) = distinct ys"
  3827 lemma distinct_union[simp]: "distinct(List.union xs ys) = distinct ys"
  3828 unfolding List.union_def
  3828 unfolding List.union_def
  3829 by(induct xs arbitrary: ys) simp_all
  3829 by(induct xs arbitrary: ys) simp_all
  3830 
  3830 
  3831 
  3831 
  3832 subsubsection \<open>@{const List.find}\<close>
  3832 subsubsection \<open>\<^const>\<open>List.find\<close>\<close>
  3833 
  3833 
  3834 lemma find_None_iff: "List.find P xs = None \<longleftrightarrow> \<not> (\<exists>x. x \<in> set xs \<and> P x)"
  3834 lemma find_None_iff: "List.find P xs = None \<longleftrightarrow> \<not> (\<exists>x. x \<in> set xs \<and> P x)"
  3835 proof (induction xs)
  3835 proof (induction xs)
  3836   case Nil thus ?case by simp
  3836   case Nil thus ?case by simp
  3837 next
  3837 next
  3866    of [] \<Rightarrow> None
  3866    of [] \<Rightarrow> None
  3867     | x # _ \<Rightarrow> Some x)"
  3867     | x # _ \<Rightarrow> Some x)"
  3868 by (induct xs) simp_all
  3868 by (induct xs) simp_all
  3869 
  3869 
  3870 
  3870 
  3871 subsubsection \<open>@{const count_list}\<close>
  3871 subsubsection \<open>\<^const>\<open>count_list\<close>\<close>
  3872 
  3872 
  3873 lemma count_notin[simp]: "x \<notin> set xs \<Longrightarrow> count_list xs x = 0"
  3873 lemma count_notin[simp]: "x \<notin> set xs \<Longrightarrow> count_list xs x = 0"
  3874 by (induction xs) auto
  3874 by (induction xs) auto
  3875 
  3875 
  3876 lemma count_le_length: "count_list xs x \<le> length xs"
  3876 lemma count_le_length: "count_list xs x \<le> length xs"
  3884     apply (auto simp: sum.If_cases sum.remove)
  3884     apply (auto simp: sum.If_cases sum.remove)
  3885     by (metis (no_types) Cons.IH Cons.prems(2) diff_eq sum.remove)
  3885     by (metis (no_types) Cons.IH Cons.prems(2) diff_eq sum.remove)
  3886 qed simp
  3886 qed simp
  3887 
  3887 
  3888 
  3888 
  3889 subsubsection \<open>@{const List.extract}\<close>
  3889 subsubsection \<open>\<^const>\<open>List.extract\<close>\<close>
  3890 
  3890 
  3891 lemma extract_None_iff: "List.extract P xs = None \<longleftrightarrow> \<not> (\<exists> x\<in>set xs. P x)"
  3891 lemma extract_None_iff: "List.extract P xs = None \<longleftrightarrow> \<not> (\<exists> x\<in>set xs. P x)"
  3892 by(auto simp: extract_def dropWhile_eq_Cons_conv split: list.splits)
  3892 by(auto simp: extract_def dropWhile_eq_Cons_conv split: list.splits)
  3893   (metis in_set_conv_decomp)
  3893   (metis in_set_conv_decomp)
  3894 
  3894 
  3912       Some (ys, y, zs) \<Rightarrow> Some (x#ys, y, zs)))"
  3912       Some (ys, y, zs) \<Rightarrow> Some (x#ys, y, zs)))"
  3913 by(auto simp add: extract_def comp_def split: list.splits)
  3913 by(auto simp add: extract_def comp_def split: list.splits)
  3914   (metis dropWhile_eq_Nil_conv list.distinct(1))
  3914   (metis dropWhile_eq_Nil_conv list.distinct(1))
  3915 
  3915 
  3916 
  3916 
  3917 subsubsection \<open>@{const remove1}\<close>
  3917 subsubsection \<open>\<^const>\<open>remove1\<close>\<close>
  3918 
  3918 
  3919 lemma remove1_append:
  3919 lemma remove1_append:
  3920   "remove1 x (xs @ ys) =
  3920   "remove1 x (xs @ ys) =
  3921   (if x \<in> set xs then remove1 x xs @ ys else xs @ remove1 x ys)"
  3921   (if x \<in> set xs then remove1 x xs @ ys else xs @ remove1 x ys)"
  3922 by (induct xs) auto
  3922 by (induct xs) auto
  3958 
  3958 
  3959 lemma remove1_idem: "x \<notin> set xs \<Longrightarrow> remove1 x xs = xs"
  3959 lemma remove1_idem: "x \<notin> set xs \<Longrightarrow> remove1 x xs = xs"
  3960 by (induct xs) simp_all
  3960 by (induct xs) simp_all
  3961 
  3961 
  3962 
  3962 
  3963 subsubsection \<open>@{const removeAll}\<close>
  3963 subsubsection \<open>\<^const>\<open>removeAll\<close>\<close>
  3964 
  3964 
  3965 lemma removeAll_filter_not_eq:
  3965 lemma removeAll_filter_not_eq:
  3966   "removeAll x = filter (\<lambda>y. x \<noteq> y)"
  3966   "removeAll x = filter (\<lambda>y. x \<noteq> y)"
  3967 proof
  3967 proof
  3968   fix xs
  3968   fix xs
  4012 lemma length_removeAll_less [termination_simp]:
  4012 lemma length_removeAll_less [termination_simp]:
  4013   "x \<in> set xs \<Longrightarrow> length (removeAll x xs) < length xs"
  4013   "x \<in> set xs \<Longrightarrow> length (removeAll x xs) < length xs"
  4014   by (auto dest: length_filter_less simp add: removeAll_filter_not_eq)
  4014   by (auto dest: length_filter_less simp add: removeAll_filter_not_eq)
  4015 
  4015 
  4016 
  4016 
  4017 subsubsection \<open>@{const replicate}\<close>
  4017 subsubsection \<open>\<^const>\<open>replicate\<close>\<close>
  4018 
  4018 
  4019 lemma length_replicate [simp]: "length (replicate n x) = n"
  4019 lemma length_replicate [simp]: "length (replicate n x) = n"
  4020 by (induct n) auto
  4020 by (induct n) auto
  4021 
  4021 
  4022 lemma replicate_eqI:
  4022 lemma replicate_eqI:
  4216 lemma fold_replicate [simp]:
  4216 lemma fold_replicate [simp]:
  4217   "fold f (replicate n x) = f x ^^ n"
  4217   "fold f (replicate n x) = f x ^^ n"
  4218 by (subst foldr_fold [symmetric]) simp_all
  4218 by (subst foldr_fold [symmetric]) simp_all
  4219 
  4219 
  4220 
  4220 
  4221 subsubsection \<open>@{const enumerate}\<close>
  4221 subsubsection \<open>\<^const>\<open>enumerate\<close>\<close>
  4222 
  4222 
  4223 lemma enumerate_simps [simp, code]:
  4223 lemma enumerate_simps [simp, code]:
  4224   "enumerate n [] = []"
  4224   "enumerate n [] = []"
  4225   "enumerate n (x # xs) = (n, x) # enumerate (Suc n) xs"
  4225   "enumerate n (x # xs) = (n, x) # enumerate (Suc n) xs"
  4226   by (simp_all add: enumerate_eq_zip upt_rec)
  4226   by (simp_all add: enumerate_eq_zip upt_rec)
  4274 lemma enumerate_map_upt:
  4274 lemma enumerate_map_upt:
  4275   "enumerate n (map f [n..<m]) = map (\<lambda>k. (k, f k)) [n..<m]"
  4275   "enumerate n (map f [n..<m]) = map (\<lambda>k. (k, f k)) [n..<m]"
  4276 by (cases "n \<le> m") (simp_all add: zip_map2 zip_same_conv_map enumerate_eq_zip)
  4276 by (cases "n \<le> m") (simp_all add: zip_map2 zip_same_conv_map enumerate_eq_zip)
  4277 
  4277 
  4278 
  4278 
  4279 subsubsection \<open>@{const rotate1} and @{const rotate}\<close>
  4279 subsubsection \<open>\<^const>\<open>rotate1\<close> and \<^const>\<open>rotate\<close>\<close>
  4280 
  4280 
  4281 lemma rotate0[simp]: "rotate 0 = id"
  4281 lemma rotate0[simp]: "rotate 0 = id"
  4282 by(simp add:rotate_def)
  4282 by(simp add:rotate_def)
  4283 
  4283 
  4284 lemma rotate_Suc[simp]: "rotate (Suc n) xs = rotate1(rotate n xs)"
  4284 lemma rotate_Suc[simp]: "rotate (Suc n) xs = rotate1(rotate n xs)"
  4378 
  4378 
  4379 lemma rotate_append: "rotate (length l) (l @ q) = q @ l"
  4379 lemma rotate_append: "rotate (length l) (l @ q) = q @ l"
  4380   by (induct l arbitrary: q) (auto simp add: rotate1_rotate_swap)
  4380   by (induct l arbitrary: q) (auto simp add: rotate1_rotate_swap)
  4381 
  4381 
  4382 
  4382 
  4383 subsubsection \<open>@{const nths} --- a generalization of @{const nth} to sets\<close>
  4383 subsubsection \<open>\<^const>\<open>nths\<close> --- a generalization of \<^const>\<open>nth\<close> to sets\<close>
  4384 
  4384 
  4385 lemma nths_empty [simp]: "nths xs {} = []"
  4385 lemma nths_empty [simp]: "nths xs {} = []"
  4386 by (auto simp add: nths_def)
  4386 by (auto simp add: nths_def)
  4387 
  4387 
  4388 lemma nths_nil [simp]: "nths [] A = []"
  4388 lemma nths_nil [simp]: "nths [] A = []"
  4481   then have "\<forall>x. x \<in> set xs \<longrightarrow> x \<noteq> a" by auto
  4481   then have "\<forall>x. x \<in> set xs \<longrightarrow> x \<noteq> a" by auto
  4482   with Cons show ?case by(simp add: nths_Cons cong:filter_cong)
  4482   with Cons show ?case by(simp add: nths_Cons cong:filter_cong)
  4483 qed
  4483 qed
  4484 
  4484 
  4485 
  4485 
  4486 subsubsection \<open>@{const subseqs} and @{const List.n_lists}\<close>
  4486 subsubsection \<open>\<^const>\<open>subseqs\<close> and \<^const>\<open>List.n_lists\<close>\<close>
  4487 
  4487 
  4488 lemma length_subseqs: "length (subseqs xs) = 2 ^ length xs"
  4488 lemma length_subseqs: "length (subseqs xs) = 2 ^ length xs"
  4489   by (induct xs) (simp_all add: Let_def)
  4489   by (induct xs) (simp_all add: Let_def)
  4490 
  4490 
  4491 lemma subseqs_powset: "set ` set (subseqs xs) = Pow (set xs)"
  4491 lemma subseqs_powset: "set ` set (subseqs xs) = Pow (set xs)"
  4546   then show ?case
  4546   then show ?case
  4547     by (auto simp: Let_def) (metis Pow_iff contra_subsetD image_eqI subseqs_powset)
  4547     by (auto simp: Let_def) (metis Pow_iff contra_subsetD image_eqI subseqs_powset)
  4548 qed simp
  4548 qed simp
  4549 
  4549 
  4550 
  4550 
  4551 subsubsection \<open>@{const splice}\<close>
  4551 subsubsection \<open>\<^const>\<open>splice\<close>\<close>
  4552 
  4552 
  4553 lemma splice_Nil2 [simp]: "splice xs [] = xs"
  4553 lemma splice_Nil2 [simp]: "splice xs [] = xs"
  4554 by (cases xs) simp_all
  4554 by (cases xs) simp_all
  4555 
  4555 
  4556 lemma length_splice[simp]: "length(splice xs ys) = length xs + length ys"
  4556 lemma length_splice[simp]: "length(splice xs ys) = length xs + length ys"
  4562 lemma splice_replicate[simp]: "splice (replicate m x) (replicate n x) = replicate (m+n) x"
  4562 lemma splice_replicate[simp]: "splice (replicate m x) (replicate n x) = replicate (m+n) x"
  4563 apply(induction "replicate m x" "replicate n x" arbitrary: m n rule: splice.induct)
  4563 apply(induction "replicate m x" "replicate n x" arbitrary: m n rule: splice.induct)
  4564 apply (auto simp add: Cons_replicate_eq dest: gr0_implies_Suc)
  4564 apply (auto simp add: Cons_replicate_eq dest: gr0_implies_Suc)
  4565 done
  4565 done
  4566 
  4566 
  4567 subsubsection \<open>@{const shuffles}\<close>
  4567 subsubsection \<open>\<^const>\<open>shuffles\<close>\<close>
  4568 
  4568 
  4569 lemma shuffles_commutes: "shuffles xs ys = shuffles ys xs"
  4569 lemma shuffles_commutes: "shuffles xs ys = shuffles ys xs"
  4570 by (induction xs ys rule: shuffles.induct) (simp_all add: Un_commute)
  4570 by (induction xs ys rule: shuffles.induct) (simp_all add: Un_commute)
  4571 
  4571 
  4572 lemma Nil_in_shuffles[simp]: "[] \<in> shuffles xs ys \<longleftrightarrow> xs = [] \<and> ys = []"
  4572 lemma Nil_in_shuffles[simp]: "[] \<in> shuffles xs ys \<longleftrightarrow> xs = [] \<and> ys = []"
  4815   fix i assume "i < length (transpose (map (map f) xs))"
  4815   fix i assume "i < length (transpose (map (map f) xs))"
  4816   thus "transpose (map (map f) xs) ! i = map (map f) (transpose xs) ! i"
  4816   thus "transpose (map (map f) xs) ! i = map (map f) (transpose xs) ! i"
  4817     by (simp add: nth_transpose filter_map comp_def)
  4817     by (simp add: nth_transpose filter_map comp_def)
  4818 qed
  4818 qed
  4819 
  4819 
  4820 subsubsection \<open>@{const min} and @{const arg_min}\<close>
  4820 subsubsection \<open>\<^const>\<open>min\<close> and \<^const>\<open>arg_min\<close>\<close>
  4821 
  4821 
  4822 lemma min_list_Min: "xs \<noteq> [] \<Longrightarrow> min_list xs = Min (set xs)"
  4822 lemma min_list_Min: "xs \<noteq> [] \<Longrightarrow> min_list xs = Min (set xs)"
  4823 by (induction xs rule: induct_list012)(auto)
  4823 by (induction xs rule: induct_list012)(auto)
  4824 
  4824 
  4825 lemma f_arg_min_list_f: "xs \<noteq> [] \<Longrightarrow> f (arg_min_list f xs) = Min (f ` (set xs))"
  4825 lemma f_arg_min_list_f: "xs \<noteq> [] \<Longrightarrow> f (arg_min_list f xs) = Min (f ` (set xs))"
  4928   by (metis UNIV_I finite_maxlen length_replicate less_irrefl)
  4928   by (metis UNIV_I finite_maxlen length_replicate less_irrefl)
  4929 
  4929 
  4930 
  4930 
  4931 subsection \<open>Sorting\<close>
  4931 subsection \<open>Sorting\<close>
  4932 
  4932 
  4933 subsubsection \<open>@{const sorted_wrt}\<close>
  4933 subsubsection \<open>\<^const>\<open>sorted_wrt\<close>\<close>
  4934 
  4934 
  4935 text \<open>Sometimes the second equation in the definition of @{const sorted_wrt} is too aggressive
  4935 text \<open>Sometimes the second equation in the definition of \<^const>\<open>sorted_wrt\<close> is too aggressive
  4936 because it relates each list element to \emph{all} its successors. Then this equation
  4936 because it relates each list element to \emph{all} its successors. Then this equation
  4937 should be removed and \<open>sorted_wrt2_simps\<close> should be added instead.\<close>
  4937 should be removed and \<open>sorted_wrt2_simps\<close> should be added instead.\<close>
  4938 
  4938 
  4939 lemma sorted_wrt1: "sorted_wrt P [x] = True"
  4939 lemma sorted_wrt1: "sorted_wrt P [x] = True"
  4940 by(simp)
  4940 by(simp)
  5002     by (auto simp: nth_append sorted_wrt_append)
  5002     by (auto simp: nth_append sorted_wrt_append)
  5003        (metis less_antisym not_less nth_mem)
  5003        (metis less_antisym not_less nth_mem)
  5004 qed
  5004 qed
  5005 
  5005 
  5006 
  5006 
  5007 subsubsection \<open>@{const sorted}\<close>
  5007 subsubsection \<open>\<^const>\<open>sorted\<close>\<close>
  5008 
  5008 
  5009 context linorder
  5009 context linorder
  5010 begin
  5010 begin
  5011 
  5011 
  5012 text \<open>Sometimes the second equation in the definition of @{const sorted} is too aggressive
  5012 text \<open>Sometimes the second equation in the definition of \<^const>\<open>sorted\<close> is too aggressive
  5013 because it relates each list element to \emph{all} its successors. Then this equation
  5013 because it relates each list element to \emph{all} its successors. Then this equation
  5014 should be removed and \<open>sorted2_simps\<close> should be added instead.
  5014 should be removed and \<open>sorted2_simps\<close> should be added instead.
  5015 Executable code is one such use case.\<close>
  5015 Executable code is one such use case.\<close>
  5016 
  5016 
  5017 lemma sorted1: "sorted [x] = True"
  5017 lemma sorted1: "sorted [x] = True"
  5193 by(simp add: sorted_sorted_wrt sorted_wrt_mono_rel[OF _ sorted_wrt_upto])
  5193 by(simp add: sorted_sorted_wrt sorted_wrt_mono_rel[OF _ sorted_wrt_upto])
  5194 
  5194 
  5195 
  5195 
  5196 subsubsection \<open>Sorting functions\<close>
  5196 subsubsection \<open>Sorting functions\<close>
  5197 
  5197 
  5198 text\<open>Currently it is not shown that @{const sort} returns a
  5198 text\<open>Currently it is not shown that \<^const>\<open>sort\<close> returns a
  5199 permutation of its input because the nicest proof is via multisets,
  5199 permutation of its input because the nicest proof is via multisets,
  5200 which are not part of Main. Alternatively one could define a function
  5200 which are not part of Main. Alternatively one could define a function
  5201 that counts the number of occurrences of an element in a list and use
  5201 that counts the number of occurrences of an element in a list and use
  5202 that instead of multisets to state the correctness property.\<close>
  5202 that instead of multisets to state the correctness property.\<close>
  5203 
  5203 
  5400 qed
  5400 qed
  5401 
  5401 
  5402 lemma sorted_enumerate [simp]: "sorted (map fst (enumerate n xs))"
  5402 lemma sorted_enumerate [simp]: "sorted (map fst (enumerate n xs))"
  5403 by (simp add: enumerate_eq_zip)
  5403 by (simp add: enumerate_eq_zip)
  5404 
  5404 
  5405 text \<open>Stability of @{const sort_key}:\<close>
  5405 text \<open>Stability of \<^const>\<open>sort_key\<close>:\<close>
  5406 
  5406 
  5407 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (sort_key f xs) = filter (\<lambda>y. f y = k) xs"
  5407 lemma sort_key_stable: "filter (\<lambda>y. f y = k) (sort_key f xs) = filter (\<lambda>y. f y = k) xs"
  5408 proof (induction xs)
  5408 proof (induction xs)
  5409   case Nil thus ?case by simp
  5409   case Nil thus ?case by simp
  5410 next
  5410 next
  5431 
  5431 
  5432 lemma sort_key_const: "sort_key (\<lambda>x. c) xs = xs"
  5432 lemma sort_key_const: "sort_key (\<lambda>x. c) xs = xs"
  5433 by (metis (mono_tags) filter_True sort_key_stable)
  5433 by (metis (mono_tags) filter_True sort_key_stable)
  5434 
  5434 
  5435 
  5435 
  5436 subsubsection \<open>@{const transpose} on sorted lists\<close>
  5436 subsubsection \<open>\<^const>\<open>transpose\<close> on sorted lists\<close>
  5437 
  5437 
  5438 lemma sorted_transpose[simp]: "sorted (rev (map length (transpose xs)))"
  5438 lemma sorted_transpose[simp]: "sorted (rev (map length (transpose xs)))"
  5439 by (auto simp: sorted_iff_nth_mono rev_nth nth_transpose
  5439 by (auto simp: sorted_iff_nth_mono rev_nth nth_transpose
  5440     length_filter_conv_card intro: card_mono)
  5440     length_filter_conv_card intro: card_mono)
  5441 
  5441 
  5584 subsubsection \<open>\<open>sorted_list_of_set\<close>\<close>
  5584 subsubsection \<open>\<open>sorted_list_of_set\<close>\<close>
  5585 
  5585 
  5586 text\<open>This function maps (finite) linearly ordered sets to sorted
  5586 text\<open>This function maps (finite) linearly ordered sets to sorted
  5587 lists. Warning: in most cases it is not a good idea to convert from
  5587 lists. Warning: in most cases it is not a good idea to convert from
  5588 sets to lists but one should convert in the other direction (via
  5588 sets to lists but one should convert in the other direction (via
  5589 @{const set}).\<close>
  5589 \<^const>\<open>set\<close>).\<close>
  5590 
  5590 
  5591 context linorder
  5591 context linorder
  5592 begin
  5592 begin
  5593 
  5593 
  5594 definition sorted_list_of_set :: "'a set \<Rightarrow> 'a list" where
  5594 definition sorted_list_of_set :: "'a set \<Rightarrow> 'a list" where
  5755 
  5755 
  5756 
  5756 
  5757 subsubsection \<open>Lists as Cartesian products\<close>
  5757 subsubsection \<open>Lists as Cartesian products\<close>
  5758 
  5758 
  5759 text\<open>\<open>set_Cons A Xs\<close>: the set of lists with head drawn from
  5759 text\<open>\<open>set_Cons A Xs\<close>: the set of lists with head drawn from
  5760 @{term A} and tail drawn from @{term Xs}.\<close>
  5760 \<^term>\<open>A\<close> and tail drawn from \<^term>\<open>Xs\<close>.\<close>
  5761 
  5761 
  5762 definition set_Cons :: "'a set \<Rightarrow> 'a list set \<Rightarrow> 'a list set" where
  5762 definition set_Cons :: "'a set \<Rightarrow> 'a list set \<Rightarrow> 'a list set" where
  5763 "set_Cons A XS = {z. \<exists>x xs. z = x # xs \<and> x \<in> A \<and> xs \<in> XS}"
  5763 "set_Cons A XS = {z. \<exists>x xs. z = x # xs \<and> x \<in> A \<and> xs \<in> XS}"
  5764 
  5764 
  5765 lemma set_Cons_sing_Nil [simp]: "set_Cons A {[]} = (%x. [x])`A"
  5765 lemma set_Cons_sing_Nil [simp]: "set_Cons A {[]} = (%x. [x])`A"
  6496 
  6496 
  6497 lemma listrel_Cons:
  6497 lemma listrel_Cons:
  6498      "listrel r `` {x#xs} = set_Cons (r``{x}) (listrel r `` {xs})"
  6498      "listrel r `` {x#xs} = set_Cons (r``{x}) (listrel r `` {xs})"
  6499 by (auto simp add: set_Cons_def intro: listrel.intros)
  6499 by (auto simp add: set_Cons_def intro: listrel.intros)
  6500 
  6500 
  6501 text \<open>Relating @{term listrel1}, @{term listrel} and closures:\<close>
  6501 text \<open>Relating \<^term>\<open>listrel1\<close>, \<^term>\<open>listrel\<close> and closures:\<close>
  6502 
  6502 
  6503 lemma listrel1_rtrancl_subset_rtrancl_listrel1:
  6503 lemma listrel1_rtrancl_subset_rtrancl_listrel1:
  6504   "listrel1 (r\<^sup>*) \<subseteq> (listrel1 r)\<^sup>*"
  6504   "listrel1 (r\<^sup>*) \<subseteq> (listrel1 r)\<^sup>*"
  6505 proof (rule subrelI)
  6505 proof (rule subrelI)
  6506   fix xs ys assume 1: "(xs,ys) \<in> listrel1 (r\<^sup>*)"
  6506   fix xs ys assume 1: "(xs,ys) \<in> listrel1 (r\<^sup>*)"
  6619   by (induction xs) simp_all
  6619   by (induction xs) simp_all
  6620 
  6620 
  6621 
  6621 
  6622 subsection \<open>Code generation\<close>
  6622 subsection \<open>Code generation\<close>
  6623 
  6623 
  6624 text\<open>Optional tail recursive version of @{const map}. Can avoid
  6624 text\<open>Optional tail recursive version of \<^const>\<open>map\<close>. Can avoid
  6625 stack overflow in some target languages.\<close>
  6625 stack overflow in some target languages.\<close>
  6626 
  6626 
  6627 fun map_tailrec_rev ::  "('a \<Rightarrow> 'b) \<Rightarrow> 'a list \<Rightarrow> 'b list \<Rightarrow> 'b list" where
  6627 fun map_tailrec_rev ::  "('a \<Rightarrow> 'b) \<Rightarrow> 'a list \<Rightarrow> 'b list \<Rightarrow> 'b list" where
  6628 "map_tailrec_rev f [] bs = bs" |
  6628 "map_tailrec_rev f [] bs = bs" |
  6629 "map_tailrec_rev f (a#as) bs = map_tailrec_rev f as (f a # bs)"
  6629 "map_tailrec_rev f (a#as) bs = map_tailrec_rev f as (f a # bs)"
  6645 definition member :: "'a list \<Rightarrow> 'a \<Rightarrow> bool" where
  6645 definition member :: "'a list \<Rightarrow> 'a \<Rightarrow> bool" where
  6646 [code_abbrev]: "member xs x \<longleftrightarrow> x \<in> set xs"
  6646 [code_abbrev]: "member xs x \<longleftrightarrow> x \<in> set xs"
  6647 
  6647 
  6648 text \<open>
  6648 text \<open>
  6649   Use \<open>member\<close> only for generating executable code.  Otherwise use
  6649   Use \<open>member\<close> only for generating executable code.  Otherwise use
  6650   @{prop "x \<in> set xs"} instead --- it is much easier to reason about.
  6650   \<^prop>\<open>x \<in> set xs\<close> instead --- it is much easier to reason about.
  6651 \<close>
  6651 \<close>
  6652 
  6652 
  6653 lemma member_rec [code]:
  6653 lemma member_rec [code]:
  6654   "member (x # xs) y \<longleftrightarrow> x = y \<or> member xs y"
  6654   "member (x # xs) y \<longleftrightarrow> x = y \<or> member xs y"
  6655   "member [] y \<longleftrightarrow> False"
  6655   "member [] y \<longleftrightarrow> False"
  6667 definition list_ex1 :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where
  6667 definition list_ex1 :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where
  6668 list_ex1_iff [code_abbrev]: "list_ex1 P xs \<longleftrightarrow> (\<exists>! x. x \<in> set xs \<and> P x)"
  6668 list_ex1_iff [code_abbrev]: "list_ex1 P xs \<longleftrightarrow> (\<exists>! x. x \<in> set xs \<and> P x)"
  6669 
  6669 
  6670 text \<open>
  6670 text \<open>
  6671   Usually you should prefer \<open>\<forall>x\<in>set xs\<close>, \<open>\<exists>x\<in>set xs\<close>
  6671   Usually you should prefer \<open>\<forall>x\<in>set xs\<close>, \<open>\<exists>x\<in>set xs\<close>
  6672   and \<open>\<exists>!x. x\<in>set xs \<and> _\<close> over @{const list_all}, @{const list_ex}
  6672   and \<open>\<exists>!x. x\<in>set xs \<and> _\<close> over \<^const>\<open>list_all\<close>, \<^const>\<open>list_ex\<close>
  6673   and @{const list_ex1} in specifications.
  6673   and \<^const>\<open>list_ex1\<close> in specifications.
  6674 \<close>
  6674 \<close>
  6675 
  6675 
  6676 lemma list_all_simps [code]:
  6676 lemma list_all_simps [code]:
  6677   "list_all P (x # xs) \<longleftrightarrow> P x \<and> list_all P xs"
  6677   "list_all P (x # xs) \<longleftrightarrow> P x \<and> list_all P xs"
  6678   "list_all P [] \<longleftrightarrow> True"
  6678   "list_all P [] \<longleftrightarrow> True"
  6856 
  6856 
  6857 definition null :: "'a list \<Rightarrow> bool" where
  6857 definition null :: "'a list \<Rightarrow> bool" where
  6858   [code_abbrev]: "null xs \<longleftrightarrow> xs = []"
  6858   [code_abbrev]: "null xs \<longleftrightarrow> xs = []"
  6859 
  6859 
  6860 text \<open>
  6860 text \<open>
  6861   Efficient emptyness check is implemented by @{const null}.
  6861   Efficient emptyness check is implemented by \<^const>\<open>null\<close>.
  6862 \<close>
  6862 \<close>
  6863 
  6863 
  6864 lemma null_rec [code]:
  6864 lemma null_rec [code]:
  6865   "null (x # xs) \<longleftrightarrow> False"
  6865   "null (x # xs) \<longleftrightarrow> False"
  6866   "null [] \<longleftrightarrow> True"
  6866   "null [] \<longleftrightarrow> True"
  6880 
  6880 
  6881 definition map_filter :: "('a \<Rightarrow> 'b option) \<Rightarrow> 'a list \<Rightarrow> 'b list" where
  6881 definition map_filter :: "('a \<Rightarrow> 'b option) \<Rightarrow> 'a list \<Rightarrow> 'b list" where
  6882   [code_post]: "map_filter f xs = map (the \<circ> f) (filter (\<lambda>x. f x \<noteq> None) xs)"
  6882   [code_post]: "map_filter f xs = map (the \<circ> f) (filter (\<lambda>x. f x \<noteq> None) xs)"
  6883 
  6883 
  6884 text \<open>
  6884 text \<open>
  6885   Operations @{const maps} and @{const map_filter} avoid
  6885   Operations \<^const>\<open>maps\<close> and \<^const>\<open>map_filter\<close> avoid
  6886   intermediate lists on execution -- do not use for proving.
  6886   intermediate lists on execution -- do not use for proving.
  6887 \<close>
  6887 \<close>
  6888 
  6888 
  6889 lemma maps_simps [code]:
  6889 lemma maps_simps [code]:
  6890   "maps f (x # xs) = f x @ maps f xs"
  6890   "maps f (x # xs) = f x @ maps f xs"
  6951 
  6951 
  6952 lemma list_ex_iff_not_all_inverval_int [code_unfold]:
  6952 lemma list_ex_iff_not_all_inverval_int [code_unfold]:
  6953   "list_ex P [i..j] \<longleftrightarrow> \<not> (all_interval_int (Not \<circ> P) i j)"
  6953   "list_ex P [i..j] \<longleftrightarrow> \<not> (all_interval_int (Not \<circ> P) i j)"
  6954   by (simp add: list_ex_iff all_interval_int_def)
  6954   by (simp add: list_ex_iff all_interval_int_def)
  6955 
  6955 
  6956 text \<open>optimized code (tail-recursive) for @{term length}\<close>
  6956 text \<open>optimized code (tail-recursive) for \<^term>\<open>length\<close>\<close>
  6957 
  6957 
  6958 definition gen_length :: "nat \<Rightarrow> 'a list \<Rightarrow> nat"
  6958 definition gen_length :: "nat \<Rightarrow> 'a list \<Rightarrow> nat"
  6959 where "gen_length n xs = n + length xs"
  6959 where "gen_length n xs = n + length xs"
  6960 
  6960 
  6961 lemma gen_length_code [code]:
  6961 lemma gen_length_code [code]:
  6986 
  6986 
  6987 open Basic_Code_Thingol;
  6987 open Basic_Code_Thingol;
  6988 
  6988 
  6989 fun implode_list t =
  6989 fun implode_list t =
  6990   let
  6990   let
  6991     fun dest_cons (IConst { sym = Code_Symbol.Constant @{const_name Cons}, ... } `$ t1 `$ t2) = SOME (t1, t2)
  6991     fun dest_cons (IConst { sym = Code_Symbol.Constant \<^const_name>\<open>Cons\<close>, ... } `$ t1 `$ t2) = SOME (t1, t2)
  6992       | dest_cons _ = NONE;
  6992       | dest_cons _ = NONE;
  6993     val (ts, t') = Code_Thingol.unfoldr dest_cons t;
  6993     val (ts, t') = Code_Thingol.unfoldr dest_cons t;
  6994   in case t'
  6994   in case t'
  6995    of IConst { sym = Code_Symbol.Constant @{const_name Nil}, ... } => SOME ts
  6995    of IConst { sym = Code_Symbol.Constant \<^const_name>\<open>Nil\<close>, ... } => SOME ts
  6996     | _ => NONE
  6996     | _ => NONE
  6997   end;
  6997   end;
  6998 
  6998 
  6999 fun print_list (target_fxy, target_cons) pr fxy t1 t2 =
  6999 fun print_list (target_fxy, target_cons) pr fxy t1 t2 =
  7000   Code_Printer.brackify_infix (target_fxy, Code_Printer.R) fxy (
  7000   Code_Printer.brackify_infix (target_fxy, Code_Printer.R) fxy (
  7010        of SOME ts =>
  7010        of SOME ts =>
  7011             Code_Printer.literal_list literals (map (pr vars Code_Printer.NOBR) ts)
  7011             Code_Printer.literal_list literals (map (pr vars Code_Printer.NOBR) ts)
  7012         | NONE =>
  7012         | NONE =>
  7013             print_list (Code_Printer.infix_cons literals) (pr vars) fxy t1 t2;
  7013             print_list (Code_Printer.infix_cons literals) (pr vars) fxy t1 t2;
  7014   in
  7014   in
  7015     Code_Target.set_printings (Code_Symbol.Constant (@{const_name Cons},
  7015     Code_Target.set_printings (Code_Symbol.Constant (\<^const_name>\<open>Cons\<close>,
  7016       [(target, SOME (Code_Printer.complex_const_syntax (2, pretty)))]))
  7016       [(target, SOME (Code_Printer.complex_const_syntax (2, pretty)))]))
  7017   end
  7017   end
  7018 
  7018 
  7019 end;
  7019 end;
  7020 \<close>
  7020 \<close>