# HG changeset patch # User haftmann # Date 1749708185 -7200 # Node ID 8f0b2daa7eaab6beda448da39a48271b5d49535b # Parent b69e4da2604bfd4cd2289dcde50cb5c47c9784eb reorganized more code-only operations diff -r b69e4da2604b -r 8f0b2daa7eaa NEWS --- a/NEWS Mon Jun 09 22:14:38 2025 +0200 +++ b/NEWS Thu Jun 12 08:03:05 2025 +0200 @@ -104,6 +104,15 @@ const List.Bleast discontinued in favour of more concise List.Least as variant of Min + const [List.]map_tailrec ~ List.map_tailrec + thm List.map_tailrec_eq [simp] + + const [List.]gen_length → List.length_tailrec + thm List.length_tailrec_eq [simp] + + const [List.]maps → List.maps + thm maps_def → List.maps_eq [simp] + The _def suffix for characteristic theorems is avoided to emphasize that these auxiliary operations are candidates for unfolding since they are variants of existing logical concepts. The [simp] declarations try to move the attention diff -r b69e4da2604b -r 8f0b2daa7eaa src/HOL/List.thy --- a/src/HOL/List.thy Mon Jun 09 22:14:38 2025 +0200 +++ b/src/HOL/List.thy Thu Jun 12 08:03:05 2025 +0200 @@ -5872,7 +5872,7 @@ lemma sorted_butlast: assumes "sorted xs" shows "sorted (butlast xs)" - by (simp add: assms butlast_conv_take sorted_wrt_take) + by (simp add: assms butlast_conv_take) lemma sorted_replicate [simp]: "sorted(replicate n x)" by(induction n) (auto) @@ -7279,7 +7279,7 @@ by (meson asymI asymD irrefl_lex lexord_asym lexord_lex) lemma asym_lenlex: "asym R \ asym (lenlex R)" - by (simp add: lenlex_def asym_inv_image asym_less_than asym_lex asym_lex_prod) + by (simp add: lenlex_def asym_inv_image asym_less_than asym_lex) lemma lenlex_append1: assumes len: "(us,xs) \ lenlex R" and eq: "length vs = length ys" @@ -8033,7 +8033,7 @@ lemma forall_atLeastAtMost_iff [code_unfold]: \(\n\{a..b}. P n) \ all_range P a (b + 1)\ - by (simp add: atLeastAtMost_eq_range all_range_iff) + by (simp add: atLeastAtMost_eq_range) lemma forall_greaterThanLessThan_iff [code_unfold]: \(\n\{a<.. all_range P (a + 1) b\ @@ -8104,27 +8104,36 @@ subsubsection \Special implementations\ +context +begin + +qualified definition map_tailrec_rev :: \('a \ 'b) \ 'a list \ 'b list \ 'b list\ \ \only for code generation\ + where map_tailrec_rev [simp]: \map_tailrec_rev f as bs = rev (map f as) @ bs\ + text \ Optional tail recursive version of \<^const>\map\. Can avoid stack overflow in some target languages. Do not use for proving. \ -fun map_tailrec_rev :: \('a \ 'b) \ 'a list \ 'b list \ 'b list\ - where - \map_tailrec_rev f [] bs = bs\ - | \map_tailrec_rev f (a # as) bs = map_tailrec_rev f as (f a # bs)\ - -lemma map_tailrec_rev: - \map_tailrec_rev f as bs = rev(map f as) @ bs\ - by (induction as arbitrary: bs) simp_all - -definition map_tailrec :: \('a \ 'b) \ 'a list \ 'b list\ - where \map_tailrec f as = rev (map_tailrec_rev f as [])\ - -text\Code equation:\ -lemma map_eq_map_tailrec: +qualified lemma map_tailrec_rev_code [code, no_atp]: + \map_tailrec_rev f [] bs = bs\ + \map_tailrec_rev f (a # as) bs = map_tailrec_rev f as (f a # bs)\ + by simp_all + +qualified definition map_tailrec :: \('a \ 'b) \ 'a list \ 'b list\ \ \only for code generation\ + where map_tailrec_eq [simp]: \map_tailrec = map\ + +qualified lemma map_tailrec_code [code, no_atp]: + \map_tailrec f as = rev (map_tailrec_rev f as [])\ + by simp + +text \Potential code equation:\ + +qualified lemma map_eq_map_tailrec: \map = map_tailrec\ - by (simp add: fun_eq_iff map_tailrec_def map_tailrec_rev) + by simp + +end definition map_filter :: \('a \ 'b option) \ 'a list \ 'b list\ where [code_post]: "map_filter f xs = map (the \ f) (filter (\x. f x \ None) xs)" @@ -8154,50 +8163,44 @@ qualified definition null :: \'a list \ bool\ \ \only for code generation\ where null_iff [code_abbrev, simp]: \null xs \ xs = []\ -lemma null_code [code, no_atp]: +qualified lemma null_code [code, no_atp]: \null [] \ True\ \null (x # xs) \ False\ by simp_all -lemma equal_Nil_null [code_unfold, no_atp]: +qualified lemma equal_Nil_null [code_unfold, no_atp]: \HOL.equal xs [] \ null xs\ \HOL.equal [] = null\ by (auto simp add: equal) -end - +qualified definition length_tailrec :: \'a list \ nat \ nat\ \ \only for code generation\ + where length_tailrec_eq [simp]: \length_tailrec xs = (+) (length xs)\ text \optimized code (tail-recursive) for \<^term>\length\\ -definition gen_length :: \nat \ 'a list \ nat\ - where \gen_length n xs = n + length xs\ - -lemma gen_length_code [code]: - \gen_length n [] = n\ - \gen_length n (x # xs) = gen_length (Suc n) xs\ - by (simp_all add: gen_length_def) - -lemma length_code [code]: - \length = gen_length 0\ - by (simp add: gen_length_def fun_eq_iff) - -hide_const (open) gen_length - - -definition maps :: \('a \ 'b list) \ 'a list \ 'b list\ - where [code_abbrev]: \maps f xs = concat (map f xs)\ +qualified lemma length_tailrec_code [code, no_atp]: + \length_tailrec [] n = n\ + \length_tailrec (x # xs) n = length_tailrec xs (Suc n)\ + by simp_all + +qualified lemma length_code [code, no_atp]: + \length xs = length_tailrec xs 0\ + by simp + +qualified definition maps :: \('a \ 'b list) \ 'a list \ 'b list\ \ \only for code generation\ + where maps_eq [code_abbrev, simp]: \maps f xs = concat (map f xs)\ text \ Operation \<^const>\maps\ avoids intermediate lists on execution -- do not use for proving. \ -lemma maps_simps [code]: - \maps f (x # xs) = f x @ maps f xs\ +qualified lemma maps_code [code, no_atp]: \maps f [] = []\ - by (simp_all add: maps_def) - -hide_const (open) maps + \maps f (x # xs) = f x @ maps f xs\ + by simp_all + +end subsubsection \Implementation of sets by lists\ @@ -8712,16 +8715,12 @@ "map f xs = rec_list Nil (%x _ y. Cons (f x) y) xs" by (induct xs) auto -lemma concat_map_maps: (* FIXME delete candidate *) - "concat (map f xs) = List.maps f xs" - by (simp add: maps_def) - lemma Ball_set_list_all: (* FIXME delete candidate *) "Ball (set xs) P \ list_all P xs" - by (simp add: list_all_iff) + by (fact Ball_set) lemma Bex_set_list_ex: (* FIXME delete candidate *) "Bex (set xs) P \ list_ex P xs" - by (simp add: list_ex_iff) + by (fact Bex_set) end