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 |
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; |
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)" |
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" |
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 |
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 |
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 |
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)" |
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)" |
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 |
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" |
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 ( |