diff --git a/thys/HOLCF-Prelude/Data_Integer.thy b/thys/HOLCF-Prelude/Data_Integer.thy --- a/thys/HOLCF-Prelude/Data_Integer.thy +++ b/thys/HOLCF-Prelude/Data_Integer.thy @@ -1,341 +1,343 @@ section \Data: Integers\ theory Data_Integer imports Numeral_Cpo Data_Bool begin domain Integer = MkI (lazy int) instance Integer :: flat proof fix x y :: Integer assume "x \ y" then show "x = \ \ x = y" by (cases x; cases y) simp_all qed instantiation Integer :: "{plus,times,minus,uminus,zero,one}" begin definition "0 = MkI\0" definition "1 = MkI\1" definition "a + b = (\ (MkI\x) (MkI\y). MkI\(x + y))\a\b" definition "a - b = (\ (MkI\x) (MkI\y). MkI\(x - y))\a\b" definition "a * b = (\ (MkI\x) (MkI\y). MkI\(x * y))\a\b" definition "- a = (\ (MkI\x). MkI\(uminus x))\a" instance .. end lemma Integer_arith_strict [simp]: fixes x :: Integer shows "\ + x = \" and "x + \ = \" and "\ * x = \" and "x * \ = \" and "\ - x = \" and "x - \ = \" and "- \ = (\::Integer)" unfolding plus_Integer_def times_Integer_def unfolding minus_Integer_def uminus_Integer_def by (cases x, simp, simp)+ lemma Integer_arith_simps [simp]: "MkI\a + MkI\b = MkI\(a + b)" "MkI\a * MkI\b = MkI\(a * b)" "MkI\a - MkI\b = MkI\(a - b)" "- MkI\a = MkI\(uminus a)" unfolding plus_Integer_def times_Integer_def unfolding minus_Integer_def uminus_Integer_def by simp_all lemma plus_MkI_MkI: "MkI\x + MkI\y = MkI\(x + y)" unfolding plus_Integer_def by simp instance Integer :: "{plus_cpo,minus_cpo,times_cpo}" by standard (simp_all add: flatdom_strict2cont) instance Integer :: comm_monoid_add proof fix a b c :: Integer show "(a + b) + c = a + (b + c)" by (cases a; cases b; cases c) simp_all show "a + b = b + a" by (cases a; cases b) simp_all show "0 + a = a" unfolding zero_Integer_def by (cases a) simp_all qed instance Integer :: comm_monoid_mult proof fix a b c :: Integer show "(a * b) * c = a * (b * c)" by (cases a; cases b; cases c) simp_all show "a * b = b * a" by (cases a; cases b) simp_all show "1 * a = a" unfolding one_Integer_def by (cases a) simp_all qed instance Integer :: comm_semiring proof fix a b c :: Integer show "(a + b) * c = a * c + b * c" by (cases a; cases b; cases c) (simp_all add: distrib_right) qed instance Integer :: semiring_numeral .. lemma Integer_add_diff_cancel [simp]: "b \ \ \ (a::Integer) + b - b = a" by (cases a; cases b) simp_all lemma zero_Integer_neq_bottom [simp]: "(0::Integer) \ \" by (simp add: zero_Integer_def) lemma one_Integer_neq_bottom [simp]: "(1::Integer) \ \" by (simp add: one_Integer_def) lemma plus_Integer_eq_bottom_iff [simp]: fixes x y :: Integer shows "x + y = \ \ x = \ \ y = \" by (cases x, simp, cases y, simp, simp) lemma diff_Integer_eq_bottom_iff [simp]: fixes x y :: Integer shows "x - y = \ \ x = \ \ y = \" by (cases x, simp, cases y, simp, simp) lemma mult_Integer_eq_bottom_iff [simp]: fixes x y :: Integer shows "x * y = \ \ x = \ \ y = \" by (cases x, simp, cases y, simp, simp) lemma minus_Integer_eq_bottom_iff [simp]: fixes x :: Integer shows "- x = \ \ x = \" by (cases x, simp, simp) lemma numeral_Integer_eq: "numeral k = MkI\(numeral k)" by (induct k, simp_all only: numeral.simps one_Integer_def plus_MkI_MkI) lemma numeral_Integer_neq_bottom [simp]: "(numeral k::Integer) \ \" unfolding numeral_Integer_eq by simp text \Symmetric versions are also needed, because the reorient simproc does not apply to these comparisons.\ lemma bottom_neq_zero_Integer [simp]: "(\::Integer) \ 0" by (simp add: zero_Integer_def) lemma bottom_neq_one_Integer [simp]: "(\::Integer) \ 1" by (simp add: one_Integer_def) lemma bottom_neq_numeral_Integer [simp]: "(\::Integer) \ numeral k" unfolding numeral_Integer_eq by simp instantiation Integer :: Ord_linear begin definition "eq = (\ (MkI\x) (MkI\y). if x = y then TT else FF)" definition "compare = (\ (MkI\x) (MkI\y). if x < y then LT else if x > y then GT else EQ)" instance proof fix x y z :: Integer show "compare\\\y = \" unfolding compare_Integer_def by simp show "compare\x\\ = \" unfolding compare_Integer_def by (cases x, simp_all) show "oppOrdering\(compare\x\y) = compare\y\x" unfolding compare_Integer_def by (cases x, cases y, simp, simp, cases y, simp, simp add: not_less less_imp_le) - { assume "compare\x\y = EQ" then show "x = y" - unfolding compare_Integer_def - by (cases x, cases y, simp, simp, - cases y, simp, simp split: if_splits) } - { assume "compare\x\y = LT" and "compare\y\z = LT" then show "compare\x\z = LT" - unfolding compare_Integer_def - by (cases x, simp, cases y, simp, cases z, simp, - auto split: if_splits) } + show "x = y" if "compare\x\y = EQ" + using that + unfolding compare_Integer_def + by (cases x, cases y, simp, simp, + cases y, simp, simp split: if_splits) + show "compare\x\z = LT" if "compare\x\y = LT" and "compare\y\z = LT" + using that + unfolding compare_Integer_def + by (cases x, simp, cases y, simp, cases z, simp, + auto split: if_splits) show "eq\x\y = is_EQ\(compare\x\y)" unfolding eq_Integer_def compare_Integer_def by (cases x, simp, cases y, simp, auto) show "compare\x\x \ EQ" unfolding compare_Integer_def by (cases x, simp_all) qed end lemma eq_MkI_MkI [simp]: "eq\(MkI\m)\(MkI\n) = (if m = n then TT else FF)" by (simp add: eq_Integer_def) lemma compare_MkI_MkI [simp]: "compare\(MkI\x)\(MkI\y) = (if x < y then LT else if x > y then GT else EQ)" unfolding compare_Integer_def by simp lemma lt_MkI_MkI [simp]: "lt\(MkI\x)\(MkI\y) = (if x < y then TT else FF)" unfolding lt_def by simp lemma le_MkI_MkI [simp]: "le\(MkI\x)\(MkI\y) = (if x \ y then TT else FF)" unfolding le_def by simp lemma eq_Integer_bottom_iff [simp]: fixes x y :: Integer shows "eq\x\y = \ \ x = \ \ y = \" by (cases x, simp, cases y, simp, simp) lemma compare_Integer_bottom_iff [simp]: fixes x y :: Integer shows "compare\x\y = \ \ x = \ \ y = \" by (cases x, simp, cases y, simp, simp) lemma lt_Integer_bottom_iff [simp]: fixes x y :: Integer shows "lt\x\y = \ \ x = \ \ y = \" by (cases x, simp, cases y, simp, simp) lemma le_Integer_bottom_iff [simp]: fixes x y :: Integer shows "le\x\y = \ \ x = \ \ y = \" by (cases x, simp, cases y, simp, simp) lemma compare_refl_Integer [simp]: "(x::Integer) \ \ \ compare\x\x = EQ" by (cases x) simp_all lemma eq_refl_Integer [simp]: "(x::Integer) \ \ \ eq\x\x = TT" by (cases x) simp_all lemma lt_refl_Integer [simp]: "(x::Integer) \ \ \ lt\x\x = FF" by (cases x) simp_all lemma le_refl_Integer [simp]: "(x::Integer) \ \ \ le\x\x = TT" by (cases x) simp_all lemma eq_Integer_numeral_simps [simp]: "eq\(0::Integer)\0 = TT" "eq\(0::Integer)\1 = FF" "eq\(1::Integer)\0 = FF" "eq\(1::Integer)\1 = TT" "eq\(0::Integer)\(numeral k) = FF" "eq\(numeral k)\(0::Integer) = FF" "k \ Num.One \ eq\(1::Integer)\(numeral k) = FF" "k \ Num.One \ eq\(numeral k)\(1::Integer) = FF" "eq\(numeral k::Integer)\(numeral l) = (if k = l then TT else FF)" unfolding zero_Integer_def one_Integer_def numeral_Integer_eq by simp_all lemma compare_Integer_numeral_simps [simp]: "compare\(0::Integer)\0 = EQ" "compare\(0::Integer)\1 = LT" "compare\(1::Integer)\0 = GT" "compare\(1::Integer)\1 = EQ" "compare\(0::Integer)\(numeral k) = LT" "compare\(numeral k)\(0::Integer) = GT" "Num.One < k \ compare\(1::Integer)\(numeral k) = LT" "Num.One < k \ compare\(numeral k)\(1::Integer) = GT" "compare\(numeral k::Integer)\(numeral l) = (if k < l then LT else if k > l then GT else EQ)" unfolding zero_Integer_def one_Integer_def numeral_Integer_eq by simp_all lemma lt_Integer_numeral_simps [simp]: "lt\(0::Integer)\0 = FF" "lt\(0::Integer)\1 = TT" "lt\(1::Integer)\0 = FF" "lt\(1::Integer)\1 = FF" "lt\(0::Integer)\(numeral k) = TT" "lt\(numeral k)\(0::Integer) = FF" "Num.One < k \ lt\(1::Integer)\(numeral k) = TT" "lt\(numeral k)\(1::Integer) = FF" "lt\(numeral k::Integer)\(numeral l) = (if k < l then TT else FF)" unfolding zero_Integer_def one_Integer_def numeral_Integer_eq by simp_all lemma le_Integer_numeral_simps [simp]: "le\(0::Integer)\0 = TT" "le\(0::Integer)\1 = TT" "le\(1::Integer)\0 = FF" "le\(1::Integer)\1 = TT" "le\(0::Integer)\(numeral k) = TT" "le\(numeral k)\(0::Integer) = FF" "le\(1::Integer)\(numeral k) = TT" "Num.One < k \ le\(numeral k)\(1::Integer) = FF" "le\(numeral k::Integer)\(numeral l) = (if k \ l then TT else FF)" unfolding zero_Integer_def one_Integer_def numeral_Integer_eq by simp_all lemma MkI_eq_0_iff [simp]: "MkI\n = 0 \ n = 0" unfolding zero_Integer_def by simp lemma MkI_eq_1_iff [simp]: "MkI\n = 1 \ n = 1" unfolding one_Integer_def by simp lemma MkI_eq_numeral_iff [simp]: "MkI\n = numeral k \ n = numeral k" unfolding numeral_Integer_eq by simp lemma MkI_0: "MkI\0 = 0" by simp lemma MkI_1: "MkI\1 = 1" by simp lemma le_plus_1: fixes m :: "Integer" assumes "le\m\n = TT" shows "le\m\(n + 1) = TT" proof - from assms have "n \ \" by auto then have "le\n\(n + 1) = TT" by (cases n) (auto, metis le_MkI_MkI less_add_one less_le_not_le one_Integer_def plus_MkI_MkI) with assms show ?thesis by (auto dest: le_trans) qed subsection \Induction rules that do not break the abstraction\ lemma nonneg_Integer_induct [consumes 1, case_names 0 step]: fixes i :: Integer assumes i_nonneg: "le\0\i = TT" and zero: "P 0" and step: "\i. le\1\i = TT \ P (i - 1) \ P i" shows "P i" proof (cases i) case bottom then have False using i_nonneg by simp then show ?thesis .. next case (MkI integer) show ?thesis proof (cases integer) case neg then have False using i_nonneg MkI by (auto simp add: zero_Integer_def one_Integer_def) then show ?thesis .. next case (nonneg nat) have "P (MkI\(int nat))" proof(induct nat) case 0 show ?case using zero by (simp add: zero_Integer_def) next case (Suc nat) have "le\1\(MkI\(int (Suc nat))) = TT" by (simp add: one_Integer_def) moreover have "P (MkI\(int (Suc nat)) - 1)" using Suc by (simp add: one_Integer_def) ultimately show ?case by (rule step) qed then show ?thesis using nonneg MkI by simp qed qed end diff --git a/thys/HOLCF-Prelude/Data_List.thy b/thys/HOLCF-Prelude/Data_List.thy --- a/thys/HOLCF-Prelude/Data_List.thy +++ b/thys/HOLCF-Prelude/Data_List.thy @@ -1,1625 +1,1621 @@ section \Data: List\ theory Data_List imports Type_Classes Data_Function Data_Bool Data_Tuple Data_Integer Numeral_Cpo begin no_notation (ASCII) Set.member ("'(:')") and Set.member ("(_/ : _)" [51, 51] 50) subsection \Datatype definition\ domain 'a list ("[_]") = Nil ("[]") | Cons (lazy head :: 'a) (lazy tail :: "['a]") (infixr ":" 65) (*FIXME: We need to standardize a mapping from Haskell fixities (0 to 9) to Isabelle ones (between 50 and 100).*) subsubsection \Section syntax for @{const Cons}\ syntax "_Cons_section" :: "'a \ ['a] \ ['a]" ("'(:')") "_Cons_section_left" :: "'a \ ['a] \ ['a]" ("'(_:')") translations "(x:)" == "(CONST Rep_cfun) (CONST Cons) x" abbreviation Cons_section_right :: "['a] \ 'a \ ['a]" ("'(:_')") where "(:xs) \ \ x. x:xs" syntax "_lazy_list" :: "args \ ['a]" ("[(_)]") translations "[x, xs]" == "x : [xs]" "[x]" == "x : []" abbreviation null :: "['a] \ tr" where "null \ is_Nil" subsection \Haskell function definitions\ instantiation list :: (Eq) Eq_strict begin fixrec eq_list :: "['a] \ ['a] \ tr" where "eq_list\[]\[] = TT" | "eq_list\(x : xs)\[] = FF" | "eq_list\[]\(y : ys) = FF" | "eq_list\(x : xs)\(y : ys) = (eq\x\y andalso eq_list\xs\ys)" instance proof fix xs :: "['a]" show "eq\xs\\ = \" by (cases xs, fixrec_simp+) show "eq\\\xs = \" by fixrec_simp qed end instance list :: (Eq_sym) Eq_sym proof fix xs ys :: "['a]" show "eq\xs\ys = eq\ys\xs" proof (induct xs arbitrary: ys) case Nil show ?case by (cases ys; simp) next case Cons then show ?case by (cases ys; simp add: eq_sym) qed simp_all qed instance list :: (Eq_equiv) Eq_equiv proof fix xs ys zs :: "['a]" show "eq\xs\xs \ FF" by (induct xs, simp_all) assume "eq\xs\ys = TT" and "eq\ys\zs = TT" then show "eq\xs\zs = TT" proof (induct xs arbitrary: ys zs) case (Nil ys zs) then show ?case by (cases ys, simp_all) next case (Cons x xs ys zs) from Cons.prems show ?case by (cases ys; cases zs) (auto intro: eq_trans Cons.hyps) qed simp_all qed instance list :: (Eq_eq) Eq_eq proof fix xs ys :: "['a]" show "eq\xs\xs \ FF" by (induct xs) simp_all assume "eq\xs\ys = TT" then show "xs = ys" proof (induct xs arbitrary: ys) case Nil then show ?case by (cases ys) auto next case Cons then show ?case by (cases ys) auto qed auto qed instantiation list :: (Ord) Ord_strict begin fixrec compare_list :: "['a] \ ['a] \ Ordering" where "compare_list\[]\[] = EQ" | "compare_list\(x : xs)\[] = GT" | "compare_list\[]\(y : ys) = LT" | "compare_list\(x : xs)\(y : ys) = thenOrdering\(compare\x\y)\(compare_list\xs\ys)" instance by standard (fixrec_simp, rename_tac x, case_tac x, fixrec_simp+) end instance list :: (Ord_linear) Ord_linear proof fix xs ys zs :: "['a]" show "oppOrdering\(compare\xs\ys) = compare\ys\xs" proof (induct xs arbitrary: ys) case Nil show ?case by (cases ys; simp) next case Cons then show ?case by (cases ys; simp add: oppOrdering_thenOrdering) qed simp_all show "xs = ys" if "compare\xs\ys = EQ" using that proof (induct xs arbitrary: ys) case Nil then show ?case by (cases ys; simp) next case Cons then show ?case by (cases ys; auto elim: compare_EQ_dest) qed simp_all show "compare\xs\zs = LT" if "compare\xs\ys = LT" and "compare\ys\zs = LT" using that proof (induct xs arbitrary: ys zs) case Nil then show ?case by (cases ys; cases zs; simp) next case (Cons a xs) then show ?case by (cases ys; cases zs) (auto dest: compare_EQ_dest compare_LT_trans) qed simp_all show "eq\xs\ys = is_EQ\(compare\xs\ys)" proof (induct xs arbitrary: ys) case Nil show ?case by (cases ys; simp) next case Cons then show ?case by (cases ys; simp add: eq_conv_compare) qed simp_all show "compare\xs\xs \ EQ" by (induct xs) simp_all qed fixrec zipWith :: "('a \ 'b \ 'c) \ ['a] \ ['b] \ ['c]" where "zipWith\f\(x : xs)\(y : ys) = f\x\y : zipWith\f\xs\ys" | "zipWith\f\(x : xs)\[] = []" | "zipWith\f\[]\ys = []" definition zip :: "['a] \ ['b] \ [\'a, 'b\]" where "zip = zipWith\\,\" fixrec zipWith3 :: "('a \ 'b \ 'c \ 'd) \ ['a] \ ['b] \ ['c] \ ['d]" where "zipWith3\f\(x : xs)\(y : ys)\(z : zs) = f\x\y\z : zipWith3\f\xs\ys\zs" | (unchecked) "zipWith3\f\xs\ys\zs = []" definition zip3 :: "['a] \ ['b] \ ['c] \ [\'a, 'b, 'c\]" where "zip3 = zipWith3\\,,\" fixrec map :: "('a \ 'b) \ ['a] \ ['b]" where "map\f\[] = []" | "map\f\(x : xs) = f\x : map\f\xs" fixrec filter :: "('a \ tr) \ ['a] \ ['a]" where "filter\P\[] = []" | "filter\P\(x : xs) = If (P\x) then x : filter\P\xs else filter\P\xs" fixrec repeat :: "'a \ ['a]" where [simp del]: "repeat\x = x : repeat\x" fixrec takeWhile :: "('a \ tr) \ ['a] \ ['a]" where "takeWhile\p\[] = []" | "takeWhile\p\(x:xs) = If p\x then x : takeWhile\p\xs else []" fixrec dropWhile :: "('a \ tr) \ ['a] \ ['a]" where "dropWhile\p\[] = []" | "dropWhile\p\(x:xs) = If p\x then dropWhile\p\xs else (x:xs)" fixrec span :: "('a -> tr) -> ['a] -> \['a],['a]\" where "span\p\[] = \[],[]\" | "span\p\(x:xs) = If p\x then (case span\p\xs of \ys, zs\ \ \x:ys,zs\) else \[], x:xs\" fixrec break :: "('a -> tr) -> ['a] -> \['a],['a]\" where "break\p = span\(neg oo p)" fixrec nth :: "['a] \ Integer \ 'a" where "nth\[]\n = \" | nth_Cons [simp del]: "nth\(x : xs)\n = If eq\n\0 then x else nth\xs\(n - 1)" (* bh: Perhaps we should rename this to 'index', to match the standard Haskell function named 'genericIndex'. *) abbreviation nth_syn :: "['a] \ Integer \ 'a" (infixl "!!" 100) where "xs !! n \ nth\xs\n" definition partition :: "('a \ tr) \ ['a] \ \['a], ['a]\" where "partition = (\ P xs. \filter\P\xs, filter\(neg oo P)\xs\)" fixrec iterate :: "('a \ 'a) \ 'a \ ['a]" where "iterate\f\x = x : iterate\f\(f\x)" fixrec foldl :: "('a -> 'b -> 'a) -> 'a -> ['b] -> 'a" where "foldl\f\z\[] = z" | "foldl\f\z\(x:xs) = foldl\f\(f\z\x)\xs" fixrec foldl1 :: "('a -> 'a -> 'a) -> ['a] -> 'a" where "foldl1\f\[] = \" | "foldl1\f\(x:xs) = foldl\f\x\xs" fixrec foldr :: "('a \ 'b \ 'b) \ 'b \ ['a] \ 'b" where "foldr\f\d\[] = d" | "foldr\f\d\(x : xs) = f\x\(foldr\f\d\xs)" fixrec foldr1 :: "('a \ 'a \ 'a) \ ['a] \ 'a" where "foldr1\f\[] = \" | "foldr1\f\[x] = x" | "foldr1\f\(x : (x':xs)) = f\x\(foldr1\f\(x':xs))" fixrec elem :: "'a::Eq \ ['a] \ tr" where "elem\x\[] = FF" | "elem\x\(y : ys) = (eq\y\x orelse elem\x\ys)" fixrec notElem :: "'a::Eq \ ['a] \ tr" where "notElem\x\[] = TT" | "notElem\x\(y : ys) = (neq\y\x andalso notElem\x\ys)" fixrec append :: "['a] \ ['a] \ ['a]" where "append\[]\ys = ys" | "append\(x : xs)\ys = x : append\xs\ys" abbreviation append_syn :: "['a] \ ['a] \ ['a]" (infixr "++" 65) where "xs ++ ys \ append\xs\ys" definition concat :: "[['a]] \ ['a]" where "concat = foldr\append\[]" definition concatMap :: "('a \ ['b]) \ ['a] \ ['b]" where "concatMap = (\ f. concat oo map\f)" fixrec last :: "['a] -> 'a" where "last\[x] = x" | "last\(_:(x:xs)) = last\(x:xs)" fixrec init :: "['a] -> ['a]" where "init\[x] = []" | "init\(x:(y:xs)) = x:(init\(y:xs))" fixrec reverse :: "['a] -> ['a]" where [simp del]:"reverse = foldl\(flip\(:))\[]" fixrec the_and :: "[tr] \ tr" where "the_and = foldr\trand\TT" fixrec the_or :: "[tr] \ tr" where "the_or = foldr\tror\FF" fixrec all :: "('a \ tr) \ ['a] \ tr" where "all\P = the_and oo (map\P)" fixrec any :: "('a \ tr) \ ['a] \ tr" where "any\P = the_or oo (map\P)" fixrec tails :: "['a] \ [['a]]" where "tails\[] = [[]]" | "tails\(x : xs) = (x : xs) : tails\xs" fixrec inits :: "['a] \ [['a]]" where "inits\[] = [[]]" | "inits\(x : xs) = [[]] ++ map\(x:)\(inits\xs)" fixrec scanr :: "('a \ 'b \ 'b) \ 'b \ ['a] \ ['b]" where "scanr\f\q0\[] = [q0]" | "scanr\f\q0\(x : xs) = ( let qs = scanr\f\q0\xs in (case qs of [] \ \ | q : qs' \ f\x\q : qs))" fixrec scanr1 :: "('a \ 'a \ 'a) \ ['a] \ ['a]" where "scanr1\f\[] = []" | "scanr1\f\(x : xs) = (case xs of [] \ [x] | x' : xs' \ ( let qs = scanr1\f\xs in (case qs of [] \ \ | q : qs' \ f\x\q : qs)))" fixrec scanl :: "('a \ 'b \ 'a) \ 'a \ ['b] \ ['a]" where "scanl\f\q\ls = q : (case ls of [] \ [] | x : xs \ scanl\f\(f\q\x)\xs)" definition scanl1 :: "('a \ 'a \ 'a) \ ['a] \ ['a]" where "scanl1 = (\ f ls. (case ls of [] \ [] | x : xs \ scanl\f\x\xs))" subsubsection \Arithmetic Sequences\ fixrec upto :: "Integer \ Integer \ [Integer]" where [simp del]: "upto\x\y = If le\x\y then x : upto\(x+1)\y else []" fixrec intsFrom :: "Integer \ [Integer]" where [simp del]: "intsFrom\x = seq\x\(x : intsFrom\(x+1))" class Enum = fixes toEnum :: "Integer \ 'a" and fromEnum :: "'a \ Integer" begin definition succ :: "'a \ 'a" where "succ = toEnum oo (+1) oo fromEnum" definition pred :: "'a \ 'a" where "pred = toEnum oo (-1) oo fromEnum" definition enumFrom :: "'a \ ['a]" where "enumFrom = (\ x. map\toEnum\(intsFrom\(fromEnum\x)))" definition enumFromTo :: "'a \ 'a \ ['a]" where "enumFromTo = (\ x y. map\toEnum\(upto\(fromEnum\x)\(fromEnum\y)))" end abbreviation enumFrom_To_syn :: "'a::Enum \ 'a \ ['a]" ("(1[_../_])") where "[m..n] \ enumFromTo\m\n" abbreviation enumFrom_syn :: "'a::Enum \ ['a]" ("(1[_..])") where "[n..] \ enumFrom\n" instantiation Integer :: Enum begin definition [simp]: "toEnum = ID" definition [simp]: "fromEnum = ID" instance .. end fixrec take :: "Integer \ ['a] \ ['a]" where [simp del]: "take\n\xs = If le\n\0 then [] else (case xs of [] \ [] | y : ys \ y : take\(n - 1)\ys)" fixrec drop :: "Integer \ ['a] \ ['a]" where [simp del]: "drop\n\xs = If le\n\0 then xs else (case xs of [] \ [] | y : ys \ drop\(n - 1)\ys)" fixrec isPrefixOf :: "['a::Eq] \ ['a] \ tr" where "isPrefixOf\[]\_ = TT" | "isPrefixOf\(x:xs)\[] = FF" | "isPrefixOf\(x:xs)\(y:ys) = (eq\x\y andalso isPrefixOf\xs\ys)" fixrec isSuffixOf :: "['a::Eq] \ ['a] \ tr" where "isSuffixOf\x\y = isPrefixOf\(reverse\x)\(reverse\y)" fixrec intersperse :: "'a \ ['a] \ ['a]" where "intersperse\sep\[] = []" | "intersperse\sep\[x] = [x]" | "intersperse\sep\(x:y:xs) = x:sep:intersperse\sep\(y:xs)" fixrec intercalate :: "['a] \ [['a]] \ ['a]" where "intercalate\xs\xss = concat\(intersperse\xs\xss)" definition replicate :: "Integer \ 'a \ ['a]" where "replicate = (\ n x. take\n\(repeat\x))" definition findIndices :: "('a \ tr) \ ['a] \ [Integer]" where "findIndices = (\ P xs. map\snd\(filter\(\ \x, i\. P\x)\(zip\xs\[0..])))" fixrec length :: "['a] \ Integer" where "length\[] = 0" | "length\(x : xs) = length\xs + 1" fixrec delete :: "'a::Eq \ ['a] \ ['a]" where "delete\x\[] = []" | "delete\x\(y : ys) = If eq\x\y then ys else y : delete\x\ys" fixrec diff :: "['a::Eq] \ ['a] \ ['a]" where "diff\xs\[] = xs" | "diff\xs\(y : ys) = diff\(delete\y\xs)\ys" abbreviation diff_syn :: "['a::Eq] \ ['a] \ ['a]" (infixl "\\\\" 70) where "xs \\\\ ys \ diff\xs\ys" subsection \Logical predicates on lists\ inductive finite_list :: "['a] \ bool" where Nil [intro!, simp]: "finite_list []" | Cons [intro!, simp]: "\x xs. finite_list xs \ finite_list (x : xs)" inductive_cases finite_listE [elim!]: "finite_list (x : xs)" lemma finite_list_upwards: assumes "finite_list xs" and "xs \ ys" shows "finite_list ys" using assms proof (induct xs arbitrary: ys) case Nil then have "ys = []" by (cases ys) simp+ then show ?case by auto next case (Cons x xs) from \x : xs \ ys\ obtain y ys' where "ys = y : ys'" by (cases ys) auto with \x : xs \ ys\ have "xs \ ys'" by auto then have "finite_list ys'" by (rule Cons.hyps) with \ys = _\ show ?case by auto qed lemma adm_finite_list [simp]: "adm finite_list" by (metis finite_list_upwards adm_upward) lemma bot_not_finite_list [simp]: "finite_list \ = False" by (rule, cases rule: finite_list.cases) auto inductive listmem :: "'a \ ['a] \ bool" where "listmem x (x : xs)" | "listmem x xs \ listmem x (y : xs)" lemma listmem_simps [simp]: shows "\ listmem x \" and "\ listmem x []" and "listmem x (y : ys) \ x = y \ listmem x ys" by (auto elim: listmem.cases intro: listmem.intros) definition set :: "['a] \ 'a set" where "set xs = {x. listmem x xs}" lemma set_simps [simp]: shows "set \ = {}" and "set [] = {}" and "set (x : xs) = insert x (set xs)" unfolding set_def by auto inductive distinct :: "['a] \ bool" where Nil [intro!, simp]: "distinct []" | Cons [intro!, simp]: "\x xs. distinct xs \ x \ set xs \ distinct (x : xs)" subsection \Properties\ lemma map_strict [simp]: "map\P\\ = \" by (fixrec_simp) lemma map_ID [simp]: "map\ID\xs = xs" by (induct xs) simp_all lemma enumFrom_intsFrom_conv [simp]: "enumFrom = intsFrom" by (intro cfun_eqI) (simp add: enumFrom_def) lemma enumFromTo_upto_conv [simp]: "enumFromTo = upto" by (intro cfun_eqI) (simp add: enumFromTo_def) lemma zipWith_strict [simp]: "zipWith\f\\\ys = \" "zipWith\f\(x : xs)\\ = \" by fixrec_simp+ lemma zip_simps [simp]: "zip\(x : xs)\(y : ys) = \x, y\ : zip\xs\ys" "zip\(x : xs)\[] = []" "zip\(x : xs)\\ = \" "zip\[]\ys = []" "zip\\\ys = \" unfolding zip_def by simp_all lemma zip_Nil2 [simp]: "xs \ \ \ zip\xs\[] = []" by (cases xs) simp_all lemma nth_strict [simp]: "nth\\\n = \" "nth\xs\\ = \" by (fixrec_simp) (cases xs, fixrec_simp+) lemma upto_strict [simp]: "upto\\\y = \" "upto\x\\ = \" by fixrec_simp+ lemma upto_simps [simp]: "n < m \ upto\(MkI\m)\(MkI\n) = []" "m \ n \ upto\(MkI\m)\(MkI\n) = MkI\m : [MkI\m+1..MkI\n]" by (subst upto.simps, simp)+ lemma filter_strict [simp]: "filter\P\\ = \" by (fixrec_simp) lemma nth_Cons_simp [simp]: "eq\n\0 = TT \ nth\(x : xs)\n = x" "eq\n\0 = FF \ nth\(x : xs)\n = nth\xs\(n - 1)" by (subst nth.simps, simp)+ lemma nth_Cons_split: "P (nth\(x : xs)\n) = ((eq\n\0 = FF \ P (nth\(x : xs)\n)) \ (eq\n\0 = TT \ P (nth\(x : xs)\n)) \ (n = \ \ P (nth\(x : xs)\n)))" (* "!!x. P (test x) = (~ (\a b. x = (a, b) & ~ P (test (a, b))))" *) apply (cases n, simp) apply (cases "n = 0", simp_all add: zero_Integer_def) done lemma nth_Cons_numeral [simp]: "(x : xs) !! 0 = x" "(x : xs) !! 1 = xs !! 0" "(x : xs) !! numeral (Num.Bit0 k) = xs !! numeral (Num.BitM k)" "(x : xs) !! numeral (Num.Bit1 k) = xs !! numeral (Num.Bit0 k)" by (simp_all add: nth_Cons numeral_Integer_eq zero_Integer_def one_Integer_def) lemma take_strict [simp]: "take\\\xs = \" by (fixrec_simp) lemma take_strict_2 [simp]: "le\1\i = TT \ take\i\\ = \" by (subst take.simps, cases "le\i\0") (auto dest: le_trans) lemma drop_strict [simp]: "drop\\\xs = \" by (fixrec_simp) lemma isPrefixOf_strict [simp]: "isPrefixOf\\\xs = \" "isPrefixOf\(x:xs)\\ = \" by (fixrec_simp)+ lemma last_strict[simp]: "last\\= \" "last\(x:\) = \" by (fixrec_simp+) lemma last_nil [simp]: "last\[] = \" by (fixrec_simp) lemma last_spine_strict: "\ finite_list xs \ last\xs = \" proof (induct xs) case (Cons a xs) then show ?case by (cases xs) auto qed auto lemma init_strict [simp]: "init\\= \" "init\(x:\) = \" by (fixrec_simp+) lemma init_nil [simp]: "init\[] = \" by (fixrec_simp) lemma strict_foldr_strict2 [simp]: "(\x. f\x\\ = \) \ foldr\f\\\xs = \" by (induct xs, auto) fixrec_simp lemma foldr_strict [simp]: "foldr\f\d\\ = \" "foldr\f\\\[] = \" "foldr\\\d\(x : xs) = \" by fixrec_simp+ lemma foldr_Cons_Nil [simp]: "foldr\(:)\[]\xs = xs" by (induct xs) simp+ lemma append_strict1 [simp]: "\ ++ ys = \" by fixrec_simp lemma foldr_append [simp]: "foldr\f\a\(xs ++ ys) = foldr\f\(foldr\f\a\ys)\xs" by (induct xs) simp+ lemma foldl_strict [simp]: "foldl\f\d\\ = \" "foldl\f\\\[] = \" by fixrec_simp+ lemma foldr1_strict [simp]: "foldr1\f\\= \" "foldr1\f\(x:\)= \" by fixrec_simp+ lemma foldl1_strict [simp]: "foldl1\f\\= \" by fixrec_simp lemma foldl_spine_strict: "\ finite_list xs \ foldl\f\x\xs = \" by (induct xs arbitrary: x) auto lemma foldl_assoc_foldr: assumes "finite_list xs" and assoc: "\x y z. f\(f\x\y)\z = f\x\(f\y\z)" and neutr1: "\x. f\z\x = x" and neutr2: "\x. f\x\z = x" shows "foldl\f\z\xs = foldr\f\z\xs" using \finite_list xs\ proof (induct xs) case (Cons x xs) from \finite_list xs\ have step: "\y. f\y\(foldl\f\z\xs) = foldl\f\(f\z\y)\xs" proof (induct xs) case (Cons x xs y) have "f\y\(foldl\f\z\(x : xs)) = f\y\(foldl\f\(f\z\x)\xs)" by auto also have "... = f\y\(f\x\(foldl\f\z\xs))" by (simp only: Cons.hyps) also have "... = f\(f\y\x)\(foldl\f\z\xs)" by (simp only: assoc) also have "... = foldl\f\(f\z\(f\y\x))\xs" by (simp only: Cons.hyps) also have "... = foldl\f\(f\(f\z\y)\x)\xs" by (simp only: assoc) also have "... = foldl\f\(f\z\y)\(x : xs)" by auto finally show ?case. qed (simp add: neutr1 neutr2) have "foldl\f\z\(x : xs) = foldl\f\(f\z\x)\xs" by auto also have "... = f\x\(foldl\f\z\xs)" by (simp only: step) also have "... = f\x\(foldr\f\z\xs)" by (simp only: Cons.hyps) also have "... = (foldr\f\z\(x:xs))" by auto finally show ?case . qed auto lemma elem_strict [simp]: "elem\x\\ = \" by fixrec_simp lemma notElem_strict [simp]: "notElem\x\\ = \" by fixrec_simp lemma list_eq_nil[simp]: "eq\l\[] = TT \ l = []" "eq\[]\l = TT \ l = []" by (cases l, auto)+ lemma take_Nil [simp]: "n \ \ \ take\n\[] = []" by (subst take.simps) (cases "le\n\0"; simp) lemma take_0 [simp]: "take\0\xs = []" "take\(MkI\0)\xs = []" by (subst take.simps, simp add: zero_Integer_def)+ lemma take_Cons [simp]: "le\1\i = TT \ take\i\(x:xs) = x : take\(i - 1)\xs" by (subst take.simps, cases "le\i\0") (auto dest: le_trans) lemma take_MkI_Cons [simp]: "0 < n \ take\(MkI\n)\(x : xs) = x : take\(MkI\(n - 1))\xs" by (subst take.simps) (simp add: zero_Integer_def one_Integer_def) lemma take_numeral_Cons [simp]: "take\1\(x : xs) = [x]" "take\(numeral (Num.Bit0 k))\(x : xs) = x : take\(numeral (Num.BitM k))\xs" "take\(numeral (Num.Bit1 k))\(x : xs) = x : take\(numeral (Num.Bit0 k))\xs" by (subst take.simps, simp add: zero_Integer_def one_Integer_def numeral_Integer_eq)+ lemma drop_0 [simp]: "drop\0\xs = xs" "drop\(MkI\0)\xs = xs" by (subst drop.simps, simp add: zero_Integer_def)+ lemma drop_pos [simp]: "le\n\0 = FF \ drop\n\xs = (case xs of [] \ [] | y : ys \ drop\(n - 1)\ys)" by (subst drop.simps, simp) lemma drop_numeral_Cons [simp]: "drop\1\(x : xs) = xs" "drop\(numeral (Num.Bit0 k))\(x : xs) = drop\(numeral (Num.BitM k))\xs" "drop\(numeral (Num.Bit1 k))\(x : xs) = drop\(numeral (Num.Bit0 k))\xs" by (subst drop.simps, simp add: zero_Integer_def one_Integer_def numeral_Integer_eq)+ lemma take_drop_append: "take\(MkI\i)\xs ++ drop\(MkI\i)\xs = xs" proof (cases i) case (nonneg n) then show ?thesis proof (induct n arbitrary : i xs) case (Suc n) thus ?case apply (subst drop.simps) apply (subst take.simps) apply (cases xs) apply (auto simp add: zero_Integer_def one_Integer_def ) done qed simp next case (neg nat) then show ?thesis apply (subst drop.simps) apply (subst take.simps) apply (auto simp add: zero_Integer_def one_Integer_def ) done qed lemma take_intsFrom_enumFrom [simp]: "take\(MkI\n)\[MkI\i..] = [MkI\i..MkI\(n+i) - 1]" proof (cases n) fix m assume "n = int m" then show ?thesis proof (induct m arbitrary: n i) case 0 then show ?case by (simp add: one_Integer_def) next case (Suc m) then have "n - 1 = int m" by simp from Suc(1) [OF this] have "take\(MkI\(n - 1))\[MkI\(i+1)..] = [MkI\(i+1)..MkI\(n - 1 + (i+1)) - 1]" . moreover have "(n - 1) + (i+1) - 1 = n + i - 1" by arith ultimately have IH: "take\(MkI\(n - 1))\[MkI\(i+1)..] = [MkI\(i+1)..MkI\(n+i) - 1]" by simp from Suc(2) have gt: "n > 0" by simp moreover have "[MkI\i..] = MkI\i : [MkI\i + 1..]" by (simp, subst intsFrom.simps) simp ultimately have *: "take\(MkI\n)\[MkI\i..] = MkI\i : take\(MkI\(n - 1))\[MkI\(i+1)..]" by (simp add: one_Integer_def) show ?case unfolding IH * using gt by (simp add: one_Integer_def) qed next fix m assume "n = - int m" then have "n \ 0" by simp then show ?thesis by (subst take.simps) (simp add: zero_Integer_def one_Integer_def) qed lemma drop_intsFrom_enumFrom [simp]: assumes "n \ 0" shows "drop\(MkI\n)\[MkI\i..] = [MkI\(n+i)..]" proof- from assms obtain n' where "n = int n'" by (cases n, auto) then show ?thesis apply(induct n' arbitrary: n i ) apply simp apply (subst intsFrom.simps[unfolded enumFrom_intsFrom_conv[symmetric]]) apply (subst drop.simps) apply (auto simp add: zero_Integer_def one_Integer_def) apply (rule cfun_arg_cong) apply (rule cfun_arg_cong) apply arith done qed lemma last_append_singleton: "finite_list xs \ last\(xs ++ [x]) = x" proof (induct xs rule:finite_list.induct) case (Cons x xs) then show ?case by (cases xs) auto qed auto lemma init_append_singleton: "finite_list xs \ init\(xs ++ [x]) = xs" proof (induct xs rule:finite_list.induct) case (Cons x xs) then show ?case by (cases xs) auto qed auto lemma append_Nil2 [simp]: "xs ++ [] = xs" by (induct xs) simp_all lemma append_assoc [simp]: "(xs ++ ys) ++ zs = xs ++ ys ++ zs" by (induct xs) simp_all lemma concat_simps [simp]: "concat\[] = []" "concat\(xs : xss) = xs ++ concat\xss" "concat\\ = \" unfolding concat_def by simp_all lemma concatMap_simps [simp]: "concatMap\f\[] = []" "concatMap\f\(x : xs) = f\x ++ concatMap\f\xs" "concatMap\f\\ = \" unfolding concatMap_def by simp_all lemma filter_append [simp]: "filter\P\(xs ++ ys) = filter\P\xs ++ filter\P\ys" proof (induct xs) case (Cons x xs) then show ?case by (cases "P\x") (auto simp: If_and_if) qed simp_all lemma elem_append [simp]: "elem\x\(xs ++ ys) = (elem\x\xs orelse elem\x\ys)" by (induct xs) auto lemma filter_filter [simp]: "filter\P\(filter\Q\xs) = filter\(\ x. Q\x andalso P\x)\xs" by (induct xs) (auto simp: If2_def [symmetric] split: split_If2) lemma filter_const_TT [simp]: "filter\(\ _. TT)\xs = xs" by (induct xs) simp_all lemma tails_strict [simp]: "tails\\ = \" by fixrec_simp lemma inits_strict [simp]: "inits\\ = \" by fixrec_simp lemma the_and_strict [simp]: "the_and\\ = \" by fixrec_simp lemma the_or_strict [simp]: "the_or\\ = \" by fixrec_simp lemma all_strict [simp]: "all\P\\ = \" by fixrec_simp lemma any_strict [simp]: "any\P\\ = \" by fixrec_simp lemma tails_neq_Nil [simp]: "tails\xs \ []" by (cases xs) simp_all lemma inits_neq_Nil [simp]: "inits\xs \ []" by (cases xs) simp_all lemma Nil_neq_tails [simp]: "[] \ tails\xs" by (cases xs) simp_all lemma Nil_neq_inits [simp]: "[] \ inits\xs" by (cases xs) simp_all lemma finite_list_not_bottom [simp]: assumes "finite_list xs" shows "xs \ \" using assms by (cases) simp_all lemma head_append [simp]: "head\(xs ++ ys) = If null\xs then head\ys else head\xs" by (cases xs) simp_all lemma filter_cong: "\x\set xs. p\x = q\x \ filter\p\xs = filter\q\xs" proof (induct arbitrary: xs rule: filter.induct) case (3 x) then show ?case by (cases xs) auto qed simp_all lemma filter_TT [simp]: assumes "\x\set xs. P\x = TT" shows "filter\P\xs = xs" by (rule filter_cong [of xs P "\ _. TT", simplified, OF assms]) lemma filter_FF [simp]: assumes "finite_list xs" and "\x\set xs. P\x = FF" shows "filter\P\xs = []" using assms by (induct xs) simp_all lemma map_cong: "\x\set xs. p\x = q\x \ map\p\xs = map\q\xs" proof (induct arbitrary: xs rule: map.induct) case (3 x) then show ?case by (cases xs) auto qed simp_all lemma finite_list_upto: "finite_list (upto\(MkI\m)\(MkI\n))" (is "?P m n") proof (cases "n - m") fix d assume "n - m = int d" then show "?P m n" proof (induct d arbitrary: m n) case (Suc d) then have "n - (m + 1) = int d" and le: "m \ n" by simp_all from Suc(1) [OF this(1)] have IH: "?P (m+1) n" . then show ?case using le by (simp add: one_Integer_def) qed (simp add: one_Integer_def) next fix d assume "n - m = - int d" then have "n \ m" by auto moreover - { assume "n = m" then have "?P m n" by (simp add: one_Integer_def) } + have "?P m n" if "n = m" using that by (simp add: one_Integer_def) moreover - { assume "n < m" then have "?P m n" by (simp add: one_Integer_def) } + have "?P m n" if "n < m" using that by (simp add: one_Integer_def) ultimately show ?thesis by arith qed lemma filter_commute: assumes "\x\set xs. (Q\x andalso P\x) = (P\x andalso Q\x)" shows "filter\P\(filter\Q\xs) = filter\Q\(filter\P\xs)" using filter_cong [of xs "\ x. Q\x andalso P\x" "\ x. P\x andalso Q\x"] and assms by simp lemma upto_append_intsFrom [simp]: assumes "m \ n" shows "upto\(MkI\m)\(MkI\n) ++ intsFrom\(MkI\n+1) = intsFrom\(MkI\m)" (is "?u m n ++ _ = ?i m") proof (cases "n - m") case (nonneg i) with assms show ?thesis proof (induct i arbitrary: m n) case (Suc i) then have "m + 1 \ n" and "n - (m + 1) = int i" by simp_all from Suc(1) [OF this] have IH: "?u (m+1) n ++ ?i (n+1) = ?i (m+1)" by (simp add: one_Integer_def) from \m + 1 \ n\ have "m \ n" by simp then have "?u m n ++ ?i (n+1) = (MkI\m : ?u (m+1) n) ++ ?i (n+1)" by (simp add: one_Integer_def) also have "\ = MkI\m : ?i (m+1)" by (simp add: IH) finally show ?case by (subst (2) intsFrom.simps) (simp add: one_Integer_def) qed (subst (2) intsFrom.simps, simp add: one_Integer_def) next case (neg i) then have "n < m" by simp with assms show ?thesis by simp qed lemma set_upto [simp]: "set (upto\(MkI\m)\(MkI\n)) = {MkI\i | i. m \ i \ i \ n}" (is "set (?u m n) = ?R m n") proof (cases "n - m") case (nonneg i) then show ?thesis proof (induct i arbitrary: m n) case (Suc i) then have *: "n - (m + 1) = int i" by simp from Suc(1) [OF *] have IH: "set (?u (m+1) n) = ?R (m+1) n" . from * have "m \ n" by simp then have "set (?u m n) = set (MkI\m : ?u (m+1) n)" by (simp add: one_Integer_def) also have "\ = insert (MkI\m) (?R (m+1) n)" by (simp add: IH) also have "\ = ?R m n" using \m \ n\ by auto finally show ?case . qed (force simp: one_Integer_def) qed simp lemma Nil_append_iff [iff]: "xs ++ ys = [] \ xs = [] \ ys = []" by (induct xs) simp_all text \This version of definedness rule for Nil is made necessary by the reorient simproc.\ lemma bottom_neq_Nil [simp]: "\ \ []" by simp text \Simproc to rewrite @{term "Nil = x"} to @{term "x = Nil"}.\ setup \ Reorient_Proc.add (fn Const(@{const_name Nil}, _) => true | _ => false) \ -simproc_setup reorient_Nil ("Nil = x") = Reorient_Proc.proc +simproc_setup reorient_Nil ("Nil = x") = \K Reorient_Proc.proc\ lemma set_append [simp]: assumes "finite_list xs" shows "set (xs ++ ys) = set xs \ set ys" using assms by (induct) simp_all lemma distinct_Cons [simp]: "distinct (x : xs) \ distinct xs \ x \ set xs" (is "?l = ?r") proof assume ?l then show ?r by (cases) simp_all next assume ?r then show ?l by auto qed lemma finite_list_append [iff]: "finite_list (xs ++ ys) \ finite_list xs \ finite_list ys" (is "?l = ?r") proof presume "finite_list xs" and "finite_list ys" then show ?l by (induct) simp_all next assume "?l" then show "?r" proof (induct "xs ++ ys" arbitrary: xs ys) case (Cons x xs) then show ?case by (cases xs) auto qed simp qed simp_all lemma distinct_append [simp]: assumes "finite_list (xs ++ ys)" shows "distinct (xs ++ ys) \ distinct xs \ distinct ys \ set xs \ set ys = {}" (is "?P xs ys") using assms proof (induct "xs ++ ys" arbitrary: xs ys) - case (Cons z zs) + case Cons': (Cons z zs) show ?case proof (cases xs) - note Cons' = Cons case (Cons u us) with Cons' have "finite_list us" and [simp]: "zs = us ++ ys" "?P us ys" by simp_all then show ?thesis by (auto simp: Cons) - qed (insert Cons, simp_all) + qed (use Cons' in simp_all) qed simp lemma finite_set [simp]: assumes "distinct xs" shows "finite (set xs)" using assms by induct auto lemma distinct_card: assumes "distinct xs" shows "MkI\(int (card (set xs))) = length\xs" using assms by (induct) (simp_all add: zero_Integer_def plus_MkI_MkI [symmetric] one_Integer_def ac_simps) lemma set_delete [simp]: fixes xs :: "['a::Eq_eq]" assumes "distinct xs" and "\x\set xs. eq\a\x \ \" shows "set (delete\a\xs) = set xs - {a}" using assms proof induct case (Cons x xs) then show ?case by (cases "eq\a\x", force+) qed simp lemma distinct_delete [simp]: fixes xs :: "['a::Eq_eq]" assumes "distinct xs" and "\x\set xs. eq\a\x \ \" shows "distinct (delete\a\xs)" using assms proof induct case (Cons x xs) then show ?case by (cases "eq\a\x", force+) qed simp lemma set_diff [simp]: fixes xs ys :: "['a::Eq_eq]" assumes "distinct ys" and "distinct xs" and "\a\set ys. \x\set xs. eq\a\x \ \" shows "set (xs \\\\ ys) = set xs - set ys" using assms proof (induct arbitrary: xs) case Nil then show ?case by (induct xs rule: distinct.induct) simp_all next case (Cons y ys) let ?xs = "delete\y\xs" from Cons have *: "\x\set xs. eq\y\x \ \" by simp from set_delete [OF \distinct xs\ this] have **: "set ?xs = set xs - {y}" . with Cons have "\a\set ys. \x\set ?xs. eq\a\x \ \" by simp moreover from * and \distinct xs\ have "distinct ?xs" by simp ultimately have "set (?xs \\\\ ys) = set ?xs - set ys" using Cons by blast then show ?case by (force simp: **) qed lemma distinct_delete_filter: fixes xs :: "['a::Eq_eq]" assumes "distinct xs" and "\x\set xs. eq\a\x \ \" shows "delete\a\xs = filter\(\ x. neq\a\x)\xs" using assms proof (induct) case (Cons x xs) then have IH: "delete\a\xs = filter\(\ x. neq\a\x)\xs" by simp show ?case proof (cases "eq\a\x") case TT have "\x\set xs. (\ x. neq\a\x)\x = (\ _. TT)\x" proof fix y assume "y \ set xs" with Cons(3, 4) have "x \ y" and "eq\a\y \ \" by auto with TT have "eq\a\y = FF" by (metis (no_types) eqD(1) trE) then show "(\ x. neq\a\x)\y = (\ _. TT)\y" by simp qed from filter_cong [OF this] and TT show ?thesis by simp qed (simp_all add: IH) qed simp lemma distinct_diff_filter: fixes xs ys :: "['a::Eq_eq]" assumes "finite_list ys" and "distinct xs" and "\a\set ys. \x\set xs. eq\a\x \ \" shows "xs \\\\ ys = filter\(\ x. neg\(elem\x\ys))\xs" using assms proof (induct arbitrary: xs) case Nil then show ?case by simp next case (Cons y ys) let ?xs = "delete\y\xs" from Cons have *: "\x\set xs. eq\y\x \ \" by simp from set_delete [OF \distinct xs\ this] have "set ?xs = set xs - {y}" . with Cons have "\a\set ys. \x\set ?xs. eq\a\x \ \" by simp moreover from * and \distinct xs\ have "distinct ?xs" by simp ultimately have "?xs \\\\ ys = filter\(\ x. neg\(elem\x\ys))\?xs" using Cons by blast then show ?case using \distinct xs\ and * by (simp add: distinct_delete_filter) qed lemma distinct_upto [intro, simp]: "distinct [MkI\m..MkI\n]" proof (cases "n - m") case (nonneg i) then show ?thesis proof (induct i arbitrary: m) case (Suc i) then have "n - (m + 1) = int i" and "m \ n" by simp_all with Suc have "distinct [MkI\(m+1)..MkI\n]" by force with \m \ n\ show ?case by (simp add: one_Integer_def) qed (simp add: one_Integer_def) qed simp lemma set_intsFrom [simp]: "set (intsFrom\(MkI\m)) = {MkI\n | n. m \ n}" (is "set (?i m) = ?I") proof show "set (?i m) \ ?I" proof fix n assume "n \ set (?i m)" then have "listmem n (?i m)" by (simp add: set_def) then show "n \ ?I" proof (induct n "(?i m)" arbitrary: m) fix x xs m assume "x : xs = ?i m" then have "x : xs = MkI\m : ?i (m+1)" by (subst (asm) intsFrom.simps) (simp add: one_Integer_def) then have [simp]: "x = MkI\m" "xs = ?i (m+1)" by simp_all show "x \ {MkI\n | n. m \ n}" by simp next fix x xs y m assume IH: "listmem x xs" "\m. xs = ?i m \ x \ {MkI\n | n. m \ n}" "y : xs = ?i m" then have "y : xs = MkI\m : ?i (m+1)" by (subst (asm) (2) intsFrom.simps) (simp add: one_Integer_def) then have [simp]: "y = MkI\m" "xs = ?i (m+1)" by simp_all from IH (2) [of "m+1"] have "x \ {MkI\n | n. m+1 \ n}" by (simp add: one_Integer_def) then show "x \ {MkI\n | n. m \ n}" by force qed qed next show "?I \ set (?i m)" proof fix x assume "x \ ?I" then obtain n where [simp]: "x = MkI\n" and "m \ n" by blast from upto_append_intsFrom [OF this(2), symmetric] have *: "set (?i m) = set (upto\(MkI\m)\(MkI\n)) \ set (?i (n+1))" using finite_list_upto [of m n] by (simp add: one_Integer_def) show "x \ set (?i m)" using \m \ n\ by (auto simp: * one_Integer_def) qed qed lemma If_eq_bottom_iff [simp]: (* FIXME: move *) "(If b then x else y = \) \ b = \ \ b = TT \ x = \ \ b = FF \ y = \" by (induct b) simp_all lemma upto_eq_bottom_iff [simp]: "upto\m\n = \ \ m = \ \ n = \" by (subst upto.simps, simp) lemma seq_eq_bottom_iff [simp]: (* FIXME: move *) "seq\x\y = \ \ x = \ \ y = \" by (simp add: seq_conv_if) lemma intsFrom_eq_bottom_iff [simp]: "intsFrom\m = \ \ m = \" by (subst intsFrom.simps, simp) lemma intsFrom_split: assumes "m \ n" shows "[MkI\n..] = [MkI\n .. MkI\(m - 1)] ++ [MkI\m..]" proof- from assms have ge: "m - n \ 0" by arith have "[MkI\n..] = (take\(MkI\(m - n)) \ [MkI\n..]) ++ (drop\(MkI\(m - n)) \ [MkI\n..])" by (subst take_drop_append, rule) also have "... = [MkI\n.. MkI\(m - 1)] ++ [MkI\m..]" by (subst drop_intsFrom_enumFrom[OF ge], auto simp add:take_intsFrom_enumFrom[simplified] one_Integer_def) finally show ?thesis . qed lemma filter_fast_forward: assumes "n+1 \ n'" and "\k . n < k \ k < n' \ \ P k" shows "filter\(\ (MkI\i) . Def (P i))\[MkI\(n+1)..] = filter\(\ (MkI\i) . Def (P i))\[MkI\n'..]" proof- from assms(1) have"[MkI\(n+1)..] = [MkI\(n+1).. MkI\(n'- 1)] ++ [MkI\n'..]" (is "_ = ?l1 ++ ?l2") by (subst intsFrom_split[of "n+1" n'], auto) moreover have "filter\(\ (MkI\i) . Def (P i))\[MkI\(n+1).. MkI\(n'- 1)] = []" apply (rule filter_FF) apply (simp, rule finite_list_upto) using assms(2) apply auto done ultimately show ?thesis by simp qed lemma null_eq_TT_iff [simp]: "null\xs = TT \ xs = []" by (cases xs) simp_all lemma null_set_empty_conv: "xs \ \ \ null\xs = TT \ set xs = {}" by (cases xs) simp_all lemma elem_TT [simp]: fixes x :: "'a::Eq_eq" shows "elem\x\xs = TT \ x \ set xs" apply (induct arbitrary: xs rule: elem.induct, simp_all) apply (rename_tac xs, case_tac xs, simp_all) apply (rename_tac a list, case_tac "eq\a\x", force+) done lemma elem_FF [simp]: fixes x :: "'a::Eq_equiv" shows "elem\x\xs = FF \ x \ set xs" by (induct arbitrary: xs rule: elem.induct, simp_all) (rename_tac xs, case_tac xs, simp_all, force) lemma length_strict [simp]: "length\\ = \" by (fixrec_simp) lemma repeat_neq_bottom [simp]: "repeat\x \ \" by (subst repeat.simps) simp lemma list_case_repeat [simp]: "list_case\a\f\(repeat\x) = f\x\(repeat\x)" by (subst repeat.simps) simp lemma length_append [simp]: "length\(xs ++ ys) = length\xs + length\ys" by (induct xs) (simp_all add: ac_simps) lemma replicate_strict [simp]: "replicate\\\x = \" by (simp add: replicate_def) lemma replicate_0 [simp]: "replicate\0\x = []" "replicate\(MkI\0)\xs = []" by (simp add: replicate_def)+ lemma Integer_add_0 [simp]: "MkI\0 + n = n" by (cases n) simp_all lemma replicate_MkI_plus_1 [simp]: "0 \ n \ replicate\(MkI\(n+1))\x = x : replicate\(MkI\n)\x" "0 \ n \ replicate\(MkI\(1+n))\x = x : replicate\(MkI\n)\x" by (simp add: replicate_def, subst take.simps, simp add: one_Integer_def zero_Integer_def)+ lemma replicate_append_plus_conv: assumes "0 \ m" and "0 \ n" shows "replicate\(MkI\m)\x ++ replicate\(MkI\n)\x = replicate\(MkI\m + MkI\n)\x" proof (cases m) case (nonneg i) with assms show ?thesis proof (induct i arbitrary: m) case (Suc i) then have ge: "int i + n \ 0" by force have "replicate\(MkI\m)\x ++ replicate\(MkI\n)\x = x : (replicate\(MkI\(int i))\x ++ replicate\(MkI\n)\x)" by (simp add: Suc) also have "\ = x : replicate\(MkI\(int i) + MkI\n)\x" using Suc by simp finally show ?case using ge by (simp add: Suc ac_simps) qed simp next case (neg i) with assms show ?thesis by simp qed lemma replicate_MkI_1 [simp]: "replicate\(MkI\1)\x = x : []" by (simp add: replicate_def, subst take.simps, simp add: zero_Integer_def one_Integer_def) lemma length_replicate [simp]: assumes "0 \ n" shows "length\(replicate\(MkI\n)\x) = MkI\n" proof (cases n) case (nonneg i) with assms show ?thesis by (induct i arbitrary: n) (simp_all add: replicate_append_plus_conv zero_Integer_def one_Integer_def) next case (neg i) with assms show ?thesis by (simp add: replicate_def) qed lemma map_oo [simp]: "map\f\(map\g\xs) = map\(f oo g)\xs" by (induct xs) simp_all lemma nth_Cons_MkI [simp]: "0 < i \ (a : xs) !! (MkI\i) = xs !! (MkI\(i - 1))" unfolding nth_Cons by (cases i, simp add: zero_Integer_def one_Integer_def) (case_tac n, simp_all) lemma map_plus_intsFrom: "map\(+ MkI\n)\(intsFrom\(MkI\m)) = intsFrom\(MkI\(m+n))" (is "?l = ?r") proof (rule list.take_lemma) fix i show "list_take i\?l = list_take i\?r" proof (induct i arbitrary: m) case (Suc i) then show ?case by (subst (1 2) intsFrom.simps) (simp add: ac_simps one_Integer_def) qed simp qed lemma plus_eq_MkI_conv: "l + n = MkI\m \ (\l' n'. l = MkI\l' \ n = MkI\n' \ m = l' + n')" by (cases l, simp) (cases n, auto) lemma length_ge_0: "length\xs = MkI\n \ n \ 0" by (induct xs arbitrary: n) (auto simp: one_Integer_def plus_eq_MkI_conv) lemma length_0_conv [simp]: "length\xs = MkI\0 \ xs = []" apply (cases xs) apply (simp_all add: one_Integer_def) apply (case_tac "length\list") apply (auto dest: length_ge_0) done lemma length_ge_1 [simp]: "length\xs = MkI\(1 + int n) \ (\u us. xs = u : us \ length\us = MkI\(int n))" (is "?l = ?r") proof assume ?r then show ?l by (auto simp: one_Integer_def) next assume 1: ?l then obtain u us where [simp]: "xs = u : us" by (cases xs) auto from 1 have 2: "1 + length\us = MkI\(1 + int n)" by (simp add: ac_simps) then have "length\us \ \" by (cases "length\us") simp_all moreover from 2 have "length\us + 1 = MkI\(int n) + 1" by (simp add: one_Integer_def ac_simps) ultimately have "length\us = MkI\(int n)" by (cases "length\us") (simp_all add: one_Integer_def) then show ?r by simp qed lemma finite_list_length_conv: "finite_list xs \ (\n. length\xs = MkI\(int n))" (is "?l = ?r") proof assume "?l" then show "?r" by (induct, auto simp: one_Integer_def) presburger next assume "?r" then obtain n where "length\xs = MkI\(int n)" by blast then show "?l" by (induct n arbitrary: xs) auto qed lemma nth_append: assumes "length\xs = MkI\n" and "n \ m" shows "(xs ++ ys) !! MkI\m = ys !! MkI\(m - n)" using assms proof (induct xs arbitrary: n m) case (Cons x xs) then have ge: "n \ 0" by (blast intro: length_ge_0) from Cons(2) have len: "length\xs = MkI\(n - 1)" by (auto simp: plus_eq_MkI_conv one_Integer_def) from Cons(3) have le: "n - 1 \ m - 1" by simp - { assume "m < 0" - with ge have ?case using Cons(3) by simp } - moreover - { assume "m = 0" + consider "m < 0" | "m = 0" | "m > 0" by arith + then show ?case + proof cases + case 1 + with ge show ?thesis using Cons(3) by simp + next + case 2 with Cons(3) and ge have "n = 0" by simp - with Cons(2) have ?case - by (auto dest: length_ge_0 simp: one_Integer_def plus_eq_MkI_conv) } - moreover - { assume "m > 0" - then have ?case - by (auto simp: Cons(1) [OF len le] zero_Integer_def one_Integer_def) } - ultimately show ?case by arith + with Cons(2) show ?thesis + by (auto dest: length_ge_0 simp: one_Integer_def plus_eq_MkI_conv) + next + case 3 + then show ?thesis + by (auto simp: Cons(1) [OF len le] zero_Integer_def one_Integer_def) + qed qed (simp_all add: zero_Integer_def) lemma replicate_nth [simp]: assumes "0 \ n" shows "(replicate\(MkI\n)\x ++ xs) !! MkI\n = xs !! MkI\0" using nth_append [OF length_replicate [OF assms], of n] by simp lemma map2_zip: "map\(\\x, y\. \x, f\y\)\(zip\xs\ys) = zip\xs\(map\f\ys)" by (induct xs arbitrary: ys) (simp_all, case_tac ys, simp_all) lemma map2_filter: "map\(\\x, y\. \x, f\y\)\(filter\(\\x, y\. P\x)\xs) = filter\(\\x, y\. P\x)\(map\(\\x, y\. \x, f\y\)\xs)" apply (induct xs, simp_all) apply (rename_tac x xs, case_tac x, simp, simp) apply (rename_tac a b, case_tac "P\a", auto) done lemma map_map_snd: "f\\ = \ \ map\f\(map\snd\xs) = map\snd\(map\(\\x, y\. \x, f\y\)\xs)" by (induct xs, simp_all, rename_tac a b, case_tac a, simp_all) lemma findIndices_Cons [simp]: "findIndices\P\(a : xs) = If P\a then 0 : map\(+1)\(findIndices\P\xs) else map\(+1)\(findIndices\P\xs)" by (auto simp: findIndices_def, subst intsFrom.simps, cases "P\a") (simp_all del: map_oo add: map_oo [symmetric] map_map_snd one_Integer_def zero_Integer_def map_plus_intsFrom [of 1 0, simplified, symmetric] map2_zip [of "(+ MkI\1)", simplified] map2_filter [of "(+ MkI\1)", simplified]) lemma filter_alt_def: fixes xs :: "['a]" shows "filter\P\xs = map\(nth\xs)\(findIndices\P\xs)" proof - - { - fix f g :: "Integer \ 'a" + have 1: "map\f\(map\snd\(filter\(\\x, i\. P\x)\(zip\xs\[MkI\i..]))) + = map\g\(map\snd\(filter\(\\x, i\. P\x)\(zip\xs\[MkI\i..])))" + if "\j\i. f\(MkI\j) = g\(MkI\j)" + for f g :: "Integer \ 'a" and P :: "'a \ tr" and i xs - assume "\j\i. f\(MkI\j) = g\(MkI\j)" - then have "map\f\(map\snd\(filter\(\\x, i\. P\x)\(zip\xs\[MkI\i..]))) - = map\g\(map\snd\(filter\(\\x, i\. P\x)\(zip\xs\[MkI\i..])))" - by (induct xs arbitrary: i, simp_all, subst (1 2) intsFrom.simps) - (rename_tac a b c, case_tac "P\a", simp_all add: one_Integer_def) - } note 1 = this - { - fix a and ys :: "['a]" - have "\i\0. nth\ys\(MkI\i) = (nth\(a : ys) oo (+1))\(MkI\i)" - by (auto simp: one_Integer_def zero_Integer_def) - } note 2 = this - { - fix a P and ys xs :: "['a]" - have "map\(nth\(a : ys) oo (+1))\(findIndices\P\xs) - = map\(nth\ys)\(findIndices\P\xs)" - by (simp add: findIndices_def 1 [OF 2, simplified, of ys P xs a] zero_Integer_def) - } note 3 = this + using that + by (induct xs arbitrary: i, simp_all, subst (1 2) intsFrom.simps) + (rename_tac a b c, case_tac "P\a", simp_all add: one_Integer_def) + have 2: "\i\0. nth\ys\(MkI\i) = (nth\(a : ys) oo (+1))\(MkI\i)" + for a and ys :: "['a]" + by (auto simp: one_Integer_def zero_Integer_def) + have 3: "map\(nth\(a : ys) oo (+1))\(findIndices\P\xs) + = map\(nth\ys)\(findIndices\P\xs)" + for a P and ys xs :: "['a]" + by (simp add: findIndices_def 1 [OF 2, simplified, of ys P xs a] zero_Integer_def) show ?thesis by (induct xs, simp_all, simp add: findIndices_def, simp add: findIndices_def) (rename_tac a b, case_tac "P\a", simp add: findIndices_def, simp_all add: 3) qed abbreviation cfun_image :: "('a \ 'b) \ 'a set \ 'b set" (infixr "`\" 90) where "f `\ A \ Rep_cfun f ` A" lemma set_map: "set (map\f\xs) = f `\ set xs" (is "?l = ?r") proof - { fix a assume "listmem a xs" then have "listmem (f\a) (map\f\xs)" - by (induct) simp_all } + have "listmem (f\a) (map\f\xs)" if "listmem a xs" for a + using that by (induct) simp_all then show "?r \ ?l" by (auto simp: set_def) next - { fix a assume "listmem a (map\f\xs)" - then have "\b. a = f\b \ listmem b xs" + have "\b. a = f\b \ listmem b xs" if "listmem a (map\f\xs)" for a + using that by (induct a "map\f\xs" arbitrary: xs) - (rename_tac xsa, case_tac xsa, auto)+ } + (rename_tac xsa, case_tac xsa, auto)+ then show "?l \ ?r" unfolding set_def by auto qed subsection \@{const reverse} and @{const reverse} induction\ text \Alternative simplification rules for @{const reverse} (easier to use for equational reasoning):\ lemma reverse_Nil [simp]: "reverse\[] = []" by (simp add: reverse.simps) lemma reverse_singleton [simp]: "reverse\[x] = [x]" by (simp add: reverse.simps) lemma reverse_strict [simp]: "reverse\\ = \" by (simp add: reverse.simps) lemma foldl_flip_Cons_append: "foldl\(flip\(:))\ys\xs = foldl\(flip\(:))\[]\xs ++ ys" proof (induct xs arbitrary: ys) case (Cons x xs) show ?case by simp (metis (no_types) Cons append.simps append_assoc) qed simp+ lemma reverse_Cons [simp]: "reverse\(x:xs) = reverse\xs ++ [x]" by (simp add: reverse.simps) (subst foldl_flip_Cons_append, rule refl) lemma reverse_append_below: "reverse\(xs ++ ys) \ reverse\ys ++ reverse\xs" apply (induction xs) apply (simp del: append_assoc add: append_assoc [symmetric])+ apply (blast intro: monofun_cfun append_assoc) done lemma reverse_reverse_below: "reverse\(reverse\xs) \ xs" proof (induction xs) case (Cons x xs) have "reverse\(reverse\(x:xs)) = reverse\(reverse\xs ++ [x])" by simp also have "\ \ reverse\[x] ++ reverse\(reverse\xs)" by (rule reverse_append_below) also have "\ = x : reverse\(reverse\xs)" by simp also have "\ \ x : xs" by (simp add: Cons) finally show ?case . qed simp+ lemma reverse_append [simp]: assumes "finite_list xs" shows "reverse\(xs ++ ys) = reverse\ys ++ reverse\xs" using assms by (induct xs) simp+ lemma reverse_spine_strict: "\ finite_list xs \ reverse\xs = \" by (auto simp add: reverse.simps foldl_spine_strict) lemma reverse_finite [simp]: assumes "finite_list xs" shows "finite_list (reverse\xs)" using assms by (induct xs) simp+ lemma reverse_reverse [simp]: assumes "finite_list xs" shows "reverse\(reverse\xs) = xs" using assms by (induct xs) simp+ lemma reverse_induct [consumes 1, case_names Nil snoc]: "\finite_list xs; P []; \x xs . finite_list xs \ P xs \ P (xs ++ [x])\ \ P xs" apply (subst reverse_reverse [symmetric]) apply assumption apply (rule finite_list.induct[where x = "reverse\xs"]) apply simp+ done lemma length_plus_not_0: "le\1\n = TT \ le\(length\xs + n)\0 = TT \ False" proof (induct xs arbitrary: n) case Nil then show ?case by auto (metis Ord_linear_class.le_trans dist_eq_tr(3) le_Integer_numeral_simps(3)) next case (Cons x xs) from Cons(1) [of "n + 1"] show ?case using Cons(2-) by (auto simp: ac_simps dest: le_plus_1) qed simp+ lemma take_length_plus_1: "length\xs \ \ \ take\(length\xs + 1)\(y:ys) = y : take\(length\xs)\ys" by (subst take.simps, cases "le\(length\xs + 1)\0") (auto, metis (no_types) length_plus_not_0 le_Integer_numeral_simps(4)) lemma le_length_plus: "length\xs \ \ \ n \ \ \ le\n\(length\xs + n) = TT" proof (induct xs arbitrary: n) case (Cons x xs) then have "le\(n + 1)\(length\xs + (n + 1)) = TT" by simp moreover have "le\n\(n + 1) = TT" using \n \ \\ by (metis le_plus_1 le_refl_Integer) ultimately have "le\n\(length\xs + (n + 1)) = TT" by (blast dest: le_trans) then show ?case by (simp add: ac_simps) qed simp+ lemma eq_take_length_isPrefixOf: "eq\xs\(take\(length\xs)\ys) \ isPrefixOf\xs\ys" proof (induct xs arbitrary: ys) - case (Cons x xs) - note IH = this + case IH: (Cons x xs) show ?case proof (cases "length\xs = \") case True then show ?thesis by simp next case False show ?thesis proof (cases ys) case bottom then show ?thesis using False using le_length_plus [of xs 1] by simp next case Nil then show ?thesis using False by simp next case (Cons z zs) then show ?thesis using False and IH [of zs] by (simp add: take_length_plus_1 monofun_cfun_arg) qed qed qed simp+ end diff --git a/thys/HOLCF-Prelude/Data_Maybe.thy b/thys/HOLCF-Prelude/Data_Maybe.thy --- a/thys/HOLCF-Prelude/Data_Maybe.thy +++ b/thys/HOLCF-Prelude/Data_Maybe.thy @@ -1,147 +1,149 @@ section \Data: Maybe\ theory Data_Maybe imports Type_Classes Data_Function Data_List Data_Bool begin domain 'a Maybe = Nothing | Just (lazy "'a") abbreviation maybe :: "'b \ ('a \ 'b) \ 'a Maybe \ 'b" where "maybe \ Maybe_case" fixrec isJust :: "'a Maybe \ tr" where "isJust\(Just\a) = TT" | "isJust\Nothing = FF" fixrec isNothing :: "'a Maybe \ tr" where "isNothing = neg oo isJust" fixrec fromJust :: "'a Maybe \ 'a" where "fromJust\(Just\a) = a" | "fromJust\Nothing = \" fixrec fromMaybe :: "'a \ 'a Maybe \ 'a" where "fromMaybe\d\Nothing = d" | "fromMaybe\d\(Just\a) = a" fixrec maybeToList :: "'a Maybe \ ['a]" where "maybeToList\Nothing = []" | "maybeToList\(Just\a) = [a]" fixrec listToMaybe :: "['a] \ 'a Maybe" where "listToMaybe\[] = Nothing" | "listToMaybe\(a:_) = Just\a" (* FIXME: The Prelude definition uses list comps, which are too advanced for our syntax *) fixrec catMaybes :: "['a Maybe] \ ['a]" where "catMaybes = concatMap\maybeToList" fixrec mapMaybe :: "('a \ 'b Maybe) \ ['a] \ ['b]" where "mapMaybe\f = catMaybes oo map\f" instantiation Maybe :: (Eq) Eq_strict begin definition "eq = maybe\(maybe\TT\(\ y. FF))\(\ x. maybe\FF\(\ y. eq\x\y))" instance proof fix x :: "'a Maybe" show "eq\x\\ = \" unfolding eq_Maybe_def by (cases x) simp_all show "eq\\\x = \" unfolding eq_Maybe_def by simp qed end lemma eq_Maybe_simps [simp]: "eq\Nothing\Nothing = TT" "eq\Nothing\(Just\y) = FF" "eq\(Just\x)\Nothing = FF" "eq\(Just\x)\(Just\y) = eq\x\y" unfolding eq_Maybe_def by simp_all instance Maybe :: (Eq_sym) Eq_sym proof fix x y :: "'a Maybe" show "eq\x\y = eq\y\x" by (cases x, simp, cases y, simp, simp, simp, cases y, simp, simp, simp add: eq_sym) qed instance Maybe :: (Eq_equiv) Eq_equiv proof fix x y z :: "'a Maybe" show "eq\x\x \ FF" by (cases x, simp_all) assume "eq\x\y = TT" and "eq\y\z = TT" then show "eq\x\z = TT" by (cases x, simp, cases y, simp, cases z, simp, simp, simp, simp, cases y, simp, simp, cases z, simp, simp, simp, fast elim: eq_trans) qed instance Maybe :: (Eq_eq) Eq_eq proof fix x y :: "'a Maybe" show "eq\x\x \ FF" by (cases x, simp_all) assume "eq\x\y = TT" then show "x = y" by (cases x, simp, cases y, simp, simp, simp, cases y, simp, simp, simp, fast) qed instantiation Maybe :: (Ord) Ord_strict begin definition "compare = maybe\(maybe\EQ\(\ y. LT))\(\ x. maybe\GT\(\ y. compare\x\y))" instance proof fix x :: "'a Maybe" show "compare\x\\ = \" unfolding compare_Maybe_def by (cases x) simp_all show "compare\\\x = \" unfolding compare_Maybe_def by simp qed end lemma compare_Maybe_simps [simp]: "compare\Nothing\Nothing = EQ" "compare\Nothing\(Just\y) = LT" "compare\(Just\x)\Nothing = GT" "compare\(Just\x)\(Just\y) = compare\x\y" unfolding compare_Maybe_def by simp_all instance Maybe :: (Ord_linear) Ord_linear proof fix x y z :: "'a Maybe" show "eq\x\y = is_EQ\(compare\x\y)" by (cases x, simp, cases y, simp, simp, simp, cases y, simp, simp, simp add: eq_conv_compare) show "oppOrdering\(compare\x\y) = compare\y\x" by (cases x, simp, (cases y, simp, simp, simp)+) show "compare\x\x \ EQ" by (cases x) simp_all - { assume "compare\x\y = EQ" then show "x = y" - by (cases x, simp, cases y, simp, simp, simp, - cases y, simp, simp, simp) (erule compare_EQ_dest) } - { assume "compare\x\y = LT" and "compare\y\z = LT" then show "compare\x\z = LT" - apply (cases x, simp) - apply (cases y, simp, simp) - apply (cases z, simp, simp, simp) - apply (cases y, simp, simp) - apply (cases z, simp, simp) - apply (auto elim: compare_LT_trans) - done } + show "x = y" if "compare\x\y = EQ" + using that + by (cases x, simp, cases y, simp, simp, simp, + cases y, simp, simp, simp) (erule compare_EQ_dest) + show "compare\x\z = LT" if "compare\x\y = LT" and "compare\y\z = LT" + using that + apply (cases x, simp) + apply (cases y, simp, simp) + apply (cases z, simp, simp, simp) + apply (cases y, simp, simp) + apply (cases z, simp, simp) + apply (auto elim: compare_LT_trans) + done qed lemma isJust_strict [simp]: "isJust\\ = \" by (fixrec_simp) lemma fromMaybe_strict [simp]: "fromMaybe\x\\ = \" by (fixrec_simp) lemma maybeToList_strict [simp]: "maybeToList\\ = \" by (fixrec_simp) end diff --git a/thys/HOLCF-Prelude/Data_Tuple.thy b/thys/HOLCF-Prelude/Data_Tuple.thy --- a/thys/HOLCF-Prelude/Data_Tuple.thy +++ b/thys/HOLCF-Prelude/Data_Tuple.thy @@ -1,234 +1,238 @@ section \Data: Tuple\ theory Data_Tuple imports Type_Classes Data_Bool begin subsection \Datatype definitions\ domain Unit ("\\") = Unit ("\\") domain ('a, 'b) Tuple2 ("\_, _\") = Tuple2 (lazy fst :: "'a") (lazy snd :: "'b") ("\_, _\") notation Tuple2 ("\,\") fixrec uncurry :: "('a \ 'b \ 'c) \ \'a, 'b\ \ 'c" where "uncurry\f\p = f\(fst\p)\(snd\p)" fixrec curry :: "(\'a, 'b\ \ 'c) \ 'a \ 'b \ 'c" where "curry\f\a\b = f\\a, b\" domain ('a, 'b, 'c) Tuple3 ("\_, _, _\") = Tuple3 (lazy "'a") (lazy "'b") (lazy "'c") ("\_, _, _\") notation Tuple3 ("\,,\") subsection \Type class instances\ instantiation Unit :: Ord_linear begin definition "eq = (\ \\ \\. TT)" definition "compare = (\ \\ \\. EQ)" instance apply standard apply (unfold eq_Unit_def compare_Unit_def) apply simp apply (rename_tac x, case_tac x, simp, simp) apply (rename_tac x y, case_tac x, simp, case_tac y, simp, simp) apply (rename_tac x y, case_tac x, case_tac y, simp, simp, case_tac y, simp, simp) apply (rename_tac x y, case_tac x, simp, case_tac y, simp, simp) apply (rename_tac x, case_tac x, simp, simp) apply (rename_tac x y z, case_tac x, simp, case_tac y, simp, case_tac z, simp, simp) done end instantiation Tuple2 :: (Eq, Eq) Eq_strict begin definition "eq = (\ \x1, y1\ \x2, y2\. eq\x1\x2 andalso eq\y1\y2)" instance proof fix x :: "\'a, 'b\" show "eq\x\\ = \" unfolding eq_Tuple2_def by (cases x, simp_all) show "eq\\\x = \" unfolding eq_Tuple2_def by simp qed end lemma eq_Tuple2_simps [simp]: "eq\\x1, y1\\\x2, y2\ = (eq\x1\x2 andalso eq\y1\y2)" unfolding eq_Tuple2_def by simp instance Tuple2 :: (Eq_sym, Eq_sym) Eq_sym proof fix x y :: "\'a, 'b\" show "eq\x\y = eq\y\x" unfolding eq_Tuple2_def by (cases x, simp, (cases y, simp, simp add: eq_sym)+) qed instance Tuple2 :: (Eq_equiv, Eq_equiv) Eq_equiv proof fix x y z :: "\'a, 'b\" show "eq\x\x \ FF" by (cases x, simp_all) - { assume "eq\x\y = TT" and "eq\y\z = TT" then show "eq\x\z = TT" - by (cases x, simp, cases y, simp, cases z, simp, simp, - fast intro: eq_trans) } + show "eq\x\z = TT" if "eq\x\y = TT" and "eq\y\z = TT" + using that + by (cases x, simp, cases y, simp, cases z, simp, simp, + fast intro: eq_trans) qed instance Tuple2 :: (Eq_eq, Eq_eq) Eq_eq proof fix x y :: "\'a, 'b\" show "eq\x\x \ FF" by (cases x, simp_all) - { assume "eq\x\y = TT" then show "x = y" - by (cases x, simp, cases y, simp, simp, fast) } + show "x = y" if "eq\x\y = TT" + using that by (cases x, simp, cases y, simp, simp, fast) qed instantiation Tuple2 :: (Ord, Ord) Ord_strict begin definition "compare = (\ \x1, y1\ \x2, y2\. thenOrdering\(compare\x1\x2)\(compare\y1\y2))" instance by standard (simp add: compare_Tuple2_def, rename_tac x, case_tac x, simp_all add: compare_Tuple2_def) end lemma compare_Tuple2_simps [simp]: "compare\\x1, y1\\\x2, y2\ = thenOrdering\(compare\x1\x2)\(compare\y1\y2)" unfolding compare_Tuple2_def by simp instance Tuple2 :: (Ord_linear, Ord_linear) Ord_linear proof fix x y z :: "\'a, 'b\" show "eq\x\y = is_EQ\(compare\x\y)" by (cases x, simp, cases y, simp, simp add: eq_conv_compare) show "oppOrdering\(compare\x\y) = compare\y\x" by (cases x, simp, cases y, simp, simp add: oppOrdering_thenOrdering) - { assume "compare\x\y = EQ" then show "x = y" - by (cases x, simp, cases y, simp, auto elim: compare_EQ_dest) } - { assume "compare\x\y = LT" and "compare\y\z = LT" then show "compare\x\z = LT" - apply (cases x, simp, cases y, simp, cases z, simp, simp) - apply (elim disjE conjE) - apply (fast elim!: compare_LT_trans) - apply (fast dest: compare_EQ_dest) - apply (fast dest: compare_EQ_dest) - apply (drule compare_EQ_dest) - apply (fast elim!: compare_LT_trans) - done } + show "x = y" if "compare\x\y = EQ" + using that by (cases x, simp, cases y, simp, auto elim: compare_EQ_dest) + show "compare\x\z = LT" if "compare\x\y = LT" and "compare\y\z = LT" + using that + apply (cases x, simp, cases y, simp, cases z, simp, simp) + apply (elim disjE conjE) + apply (fast elim!: compare_LT_trans) + apply (fast dest: compare_EQ_dest) + apply (fast dest: compare_EQ_dest) + apply (drule compare_EQ_dest) + apply (fast elim!: compare_LT_trans) + done show "compare\x\x \ EQ" by (cases x, simp_all) qed instantiation Tuple3 :: (Eq, Eq, Eq) Eq_strict begin definition "eq = (\ \x1, y1, z1\ \x2, y2, z2\. eq\x1\x2 andalso eq\y1\y2 andalso eq\z1\z2)" instance proof fix x :: "\'a, 'b, 'c\" show "eq\x\\ = \" unfolding eq_Tuple3_def by (cases x, simp_all) show "eq\\\x = \" unfolding eq_Tuple3_def by simp qed end lemma eq_Tuple3_simps [simp]: "eq\\x1, y1, z1\\\x2, y2, z2\ = (eq\x1\x2 andalso eq\y1\y2 andalso eq\z1\z2)" unfolding eq_Tuple3_def by simp instance Tuple3 :: (Eq_sym, Eq_sym, Eq_sym) Eq_sym proof fix x y :: "\'a, 'b, 'c\" show "eq\x\y = eq\y\x" unfolding eq_Tuple3_def by (cases x, simp, (cases y, simp, simp add: eq_sym)+) qed instance Tuple3 :: (Eq_equiv, Eq_equiv, Eq_equiv) Eq_equiv proof fix x y z :: "\'a, 'b, 'c\" show "eq\x\x \ FF" by (cases x, simp_all) - { assume "eq\x\y = TT" and "eq\y\z = TT" then show "eq\x\z = TT" - by (cases x, simp, cases y, simp, cases z, simp, simp, - fast intro: eq_trans) } + show "eq\x\z = TT" if "eq\x\y = TT" and "eq\y\z = TT" + using that + by (cases x, simp, cases y, simp, cases z, simp, simp, + fast intro: eq_trans) qed instance Tuple3 :: (Eq_eq, Eq_eq, Eq_eq) Eq_eq proof fix x y :: "\'a, 'b, 'c\" show "eq\x\x \ FF" by (cases x, simp_all) - { assume "eq\x\y = TT" then show "x = y" - by (cases x, simp, cases y, simp, simp, fast) } + show "x = y" if "eq\x\y = TT" + using that by (cases x, simp, cases y, simp, simp, fast) qed instantiation Tuple3 :: (Ord, Ord, Ord) Ord_strict begin definition "compare = (\ \x1, y1, z1\ \x2, y2, z2\. thenOrdering\(compare\x1\x2)\(thenOrdering\(compare\y1\y2)\(compare\z1\z2)))" instance by standard (simp add: compare_Tuple3_def, rename_tac x, case_tac x, simp_all add: compare_Tuple3_def) end lemma compare_Tuple3_simps [simp]: "compare\\x1, y1, z1\\\x2, y2, z2\ = thenOrdering\(compare\x1\x2)\ (thenOrdering\(compare\y1\y2)\(compare\z1\z2))" unfolding compare_Tuple3_def by simp instance Tuple3 :: (Ord_linear, Ord_linear, Ord_linear) Ord_linear proof fix x y z :: "\'a, 'b, 'c\" show "eq\x\y = is_EQ\(compare\x\y)" by (cases x, simp, cases y, simp, simp add: eq_conv_compare) show "oppOrdering\(compare\x\y) = compare\y\x" by (cases x, simp, cases y, simp, simp add: oppOrdering_thenOrdering) - { assume "compare\x\y = EQ" then show "x = y" - by (cases x, simp, cases y, simp, auto elim: compare_EQ_dest) } - { assume "compare\x\y = LT" and "compare\y\z = LT" then show "compare\x\z = LT" - apply (cases x, simp, cases y, simp, cases z, simp, simp) - apply (elim disjE conjE) - apply (fast elim!: compare_LT_trans) - apply (fast dest: compare_EQ_dest) - apply (fast dest: compare_EQ_dest) + show "x = y" if "compare\x\y = EQ" + using that by (cases x, simp, cases y, simp, auto elim: compare_EQ_dest) + show "compare\x\z = LT" if "compare\x\y = LT" and "compare\y\z = LT" + using that + apply (cases x, simp, cases y, simp, cases z, simp, simp) + apply (elim disjE conjE) + apply (fast elim!: compare_LT_trans) apply (fast dest: compare_EQ_dest) apply (fast dest: compare_EQ_dest) - apply (drule compare_EQ_dest) - apply (fast elim!: compare_LT_trans) + apply (fast dest: compare_EQ_dest) apply (fast dest: compare_EQ_dest) - apply (fast dest: compare_EQ_dest) - apply (fast dest: compare_EQ_dest elim!: compare_LT_trans) - done } + apply (drule compare_EQ_dest) + apply (fast elim!: compare_LT_trans) + apply (fast dest: compare_EQ_dest) + apply (fast dest: compare_EQ_dest) + apply (fast dest: compare_EQ_dest elim!: compare_LT_trans) + done show "compare\x\x \ EQ" by (cases x, simp_all) qed end diff --git a/thys/HOLCF-Prelude/Definedness.thy b/thys/HOLCF-Prelude/Definedness.thy --- a/thys/HOLCF-Prelude/Definedness.thy +++ b/thys/HOLCF-Prelude/Definedness.thy @@ -1,224 +1,221 @@ section \Definedness\ theory Definedness imports Data_List begin text \ This is an attempt for a setup for better handling bottom, by a better simp setup, and less breaking the abstractions. \ definition defined :: "'a :: pcpo \ bool" where "defined x = (x \ \)" lemma defined_bottom [simp]: "\ defined \" by (simp add: defined_def) lemma defined_seq [simp]: "defined x \ seq\x\y = y" by (simp add: defined_def) consts val :: "'a::type \ 'b::type" ("\_\") text \val for booleans\ definition val_Bool :: "tr \ bool" where "val_Bool i = (THE j. i = Def j)" adhoc_overloading val val_Bool lemma defined_Bool_simps [simp]: "defined (Def i)" "defined TT" "defined FF" by (simp_all add: defined_def) lemma val_Bool_simp1 [simp]: "\Def i\ = i" by (simp_all add: val_Bool_def TT_def FF_def) lemma val_Bool_simp2 [simp]: "\TT\ = True" "\FF\ = False" by (simp_all add: TT_def FF_def) lemma IF_simps [simp]: "defined b \ \ b \ \ (If b then x else y) = x" "defined b \ \ b \ = False \ (If b then x else y) = y" by (cases b, simp_all)+ lemma defined_neg [simp]: "defined (neg\b) \ defined b" by (cases b, auto) lemma val_Bool_neg [simp]: "defined b \ \ neg \ b \ = (\ \ b \)" by (cases b, auto) text \val for integers\ definition val_Integer :: "Integer \ int" where "val_Integer i = (THE j. i = MkI\j)" adhoc_overloading val val_Integer lemma defined_Integer_simps [simp]: "defined (MkI\i)" "defined (0::Integer)" "defined (1::Integer)" by (simp_all add: defined_def) lemma defined_numeral [simp]: "defined (numeral x :: Integer)" by (simp add: defined_def) lemma val_Integer_simps [simp]: "\MkI\i\ = i" "\0\ = 0" "\1\ = 1" by (simp_all add: val_Integer_def) lemma val_Integer_numeral [simp]: "\ numeral x :: Integer \ = numeral x" by (simp_all add: val_Integer_def) lemma val_Integer_to_MkI: "defined i \ i = (MkI \ \ i \)" apply (cases i) apply (auto simp add: val_Integer_def defined_def) done lemma defined_Integer_minus [simp]: "defined i \ defined j \ defined (i - (j::Integer))" apply (cases i, auto) apply (cases j, auto) done lemma val_Integer_minus [simp]: "defined i \ defined j \ \ i - j \ = \ i \ - \ j \" apply (cases i, auto) apply (cases j, auto) done lemma defined_Integer_plus [simp]: "defined i \ defined j \ defined (i + (j::Integer))" apply (cases i, auto) apply (cases j, auto) done lemma val_Integer_plus [simp]: "defined i \ defined j \ \ i + j \ = \ i \ + \ j \" apply (cases i, auto) apply (cases j, auto) done lemma defined_Integer_eq [simp]: "defined (eq\a\b) \ defined a \ defined (b::Integer)" apply (cases a, simp) apply (cases b, simp) apply simp done lemma val_Integer_eq [simp]: "defined a \ defined b \ \ eq\a\b \ = (\ a \ = (\ b \ :: int))" apply (cases a, simp) apply (cases b, simp) apply simp done text \Full induction for non-negative integers\ lemma nonneg_full_Int_induct [consumes 1, case_names neg Suc]: assumes defined: "defined i" assumes neg: "\ i. defined i \ \i\ < 0 \ P i" assumes step: "\ i. defined i \ 0 \ \i\ \ (\ j. defined j \ \ j \ < \ i \ \ P j) \ P i" shows "P (i::Integer)" proof (cases i) case bottom then have False using defined by simp then show ?thesis .. next case (MkI integer) show ?thesis proof (cases integer) case neg then show ?thesis using assms(2) MkI by simp next case (nonneg nat) have "P (MkI\(int nat))" proof(induction nat rule:full_nat_induct) case (1 nat) have "defined (MkI\(int nat))" by simp moreover have "0 \ \ MkI\(int nat) \" by simp moreover - { fix j::Integer - assume "defined j" and le: "\ j \ < \ MkI\(int nat) \" - have "P j" - proof(cases j) - case bottom with \defined j\ show ?thesis by simp + have "P j" if "defined j" and le: "\ j \ < \ MkI\(int nat) \" for j::Integer + proof(cases j) + case bottom with \defined j\ show ?thesis by simp + next + case (MkI integer) + show ?thesis + proof(cases integer) + case (neg nat) + have "\j\ < 0" using neg MkI by simp + with \defined j\ + show ?thesis by (rule assms(2)) next - case (MkI integer) - show ?thesis - proof(cases integer) - case (neg nat) - have "\j\ < 0" using neg MkI by simp - with \defined j\ - show ?thesis by (rule assms(2)) - next - case (nonneg m) - have "Suc m \ nat" using le nonneg MkI by simp - then have "P (MkI\(int m))" by (metis "1.IH") - then show ?thesis using nonneg MkI by simp - qed + case (nonneg m) + have "Suc m \ nat" using le nonneg MkI by simp + then have "P (MkI\(int m))" by (metis "1.IH") + then show ?thesis using nonneg MkI by simp qed - } + qed ultimately show ?case by (rule step) qed then show ?thesis using nonneg MkI by simp qed qed text \Some list lemmas re-done with the new setup.\ lemma nth_tail: (* TODO: move *) "defined n \ \ n \ \ 0 \ tail\xs !! n = xs !! (1 + n)" apply (cases xs, simp_all) apply (cases n, simp) apply (simp add: one_Integer_def zero_Integer_def) done lemma nth_zipWith: (* TODO: move *) assumes f1 [simp]: "\y. f\\\y = \" assumes f2 [simp]: "\x. f\x\\ = \" shows "zipWith\f\xs\ys !! n = f\(xs !! n)\(ys !! n)" proof (induct xs arbitrary: ys n) case (Cons x xs ys n) then show ?case by (cases ys, simp_all split:nth_Cons_split) qed simp_all lemma nth_neg [simp]: "defined n \ \ n \ < 0 \ nth\xs\n = \" proof (induction xs arbitrary: n) have [simp]: "eq\n\0 = TT \ (n::Integer) = 0" for n by (cases n, auto simp add: zero_Integer_def) case (Cons a xs n) have "eq\n\0 = FF" using Cons.prems by (cases "eq\n\0") auto then show ?case using Cons.prems by (auto intro: Cons.IH) qed simp_all lemma nth_Cons_simp [simp]: "defined n \ \ n \ = 0 \ nth\(x : xs)\n = x" "defined n \ \ n \ > 0 \ nth\(x : xs)\n = nth\xs\(n - 1)" proof - assume "defined n" and "\ n \ = 0" then have "n = 0" by (cases n) auto then show "nth\(x : xs)\n = x" by simp next assume "defined n" and "\ n \ > 0" then have "eq\n\0 = FF" by (cases "eq\n\0") auto then show "nth\(x : xs)\n = nth\xs\(n - 1)" by simp qed end diff --git a/thys/HOLCF-Prelude/Type_Classes.thy b/thys/HOLCF-Prelude/Type_Classes.thy --- a/thys/HOLCF-Prelude/Type_Classes.thy +++ b/thys/HOLCF-Prelude/Type_Classes.thy @@ -1,276 +1,279 @@ section \Type Classes\ theory Type_Classes imports HOLCF_Main begin subsection \Eq class\ class Eq = fixes eq :: "'a \ 'a \ tr" text \ The Haskell type class does allow /= to be specified separately. For now, we assume that all modeled type classes use the default implementation, or an equivalent. \ fixrec neq :: "'a::Eq \ 'a \ tr" where "neq\x\y = neg\(eq\x\y)" class Eq_strict = Eq + assumes eq_strict [simp]: "eq\x\\ = \" "eq\\\y = \" class Eq_sym = Eq_strict + assumes eq_sym: "eq\x\y = eq\y\x" class Eq_equiv = Eq_sym + assumes eq_self_neq_FF [simp]: "eq\x\x \ FF" and eq_trans: "eq\x\y = TT \ eq\y\z = TT \ eq\x\z = TT" begin lemma eq_refl: "eq\x\x \ \ \ eq\x\x = TT" by (cases "eq\x\x") simp+ end class Eq_eq = Eq_sym + assumes eq_self_neq_FF': "eq\x\x \ FF" and eq_TT_dest: "eq\x\y = TT \ x = y" begin subclass Eq_equiv by standard (auto simp: eq_self_neq_FF' dest: eq_TT_dest) lemma eqD [dest]: "eq\x\y = TT \ x = y" "eq\x\y = FF \ x \ y" by (auto elim: eq_TT_dest) end subsubsection \Class instances\ instantiation lift :: (countable) Eq_eq begin definition "eq \ (\(Def x) (Def y). Def (x = y))" instance by standard (auto simp: eq_lift_def flift1_def split: lift.splits) end lemma eq_ONE_ONE [simp]: "eq\ONE\ONE = TT" unfolding ONE_def eq_lift_def by simp subsection \Ord class\ domain Ordering = LT | EQ | GT definition oppOrdering :: "Ordering \ Ordering" where "oppOrdering = (\ x. case x of LT \ GT | EQ \ EQ | GT \ LT)" lemma oppOrdering_simps [simp]: "oppOrdering\LT = GT" "oppOrdering\EQ = EQ" "oppOrdering\GT = LT" "oppOrdering\\ = \" unfolding oppOrdering_def by simp_all class Ord = Eq + fixes compare :: "'a \ 'a \ Ordering" begin definition lt :: "'a \ 'a \ tr" where "lt = (\ x y. case compare\x\y of LT \ TT | EQ \ FF | GT \ FF)" definition le :: "'a \ 'a \ tr" where "le = (\ x y. case compare\x\y of LT \ TT | EQ \ TT | GT \ FF)" lemma lt_eq_TT_iff: "lt\x\y = TT \ compare\x\y = LT" by (cases "compare\x\y") (simp add: lt_def)+ end class Ord_strict = Ord + assumes compare_strict [simp]: "compare\\\y = \" "compare\x\\ = \" begin lemma lt_strict [simp]: shows "lt\\\x = \" and "lt\x\\ = \" by (simp add: lt_def)+ lemma le_strict [simp]: shows "le\\\x = \" and "le\x\\ = \" by (simp add: le_def)+ end text \TODO: It might make sense to have a class for preorders too, analogous to class \eq_equiv\.\ class Ord_linear = Ord_strict + assumes eq_conv_compare: "eq\x\y = is_EQ\(compare\x\y)" and oppOrdering_compare [simp]: "oppOrdering\(compare\x\y) = compare\y\x" and compare_EQ_dest: "compare\x\y = EQ \ x = y" and compare_self_below_EQ: "compare\x\x \ EQ" and compare_LT_trans: "compare\x\y = LT \ compare\y\z = LT \ compare\x\z = LT" (*BH: Is this set of axioms complete?*) (*CS: How about totality of the order?*) begin lemma eq_TT_dest: "eq\x\y = TT \ x = y" by (cases "compare\x\y") (auto dest: compare_EQ_dest simp: eq_conv_compare)+ lemma le_iff_lt_or_eq: "le\x\y = TT \ lt\x\y = TT \ eq\x\y = TT" by (cases "compare\x\y") (simp add: le_def lt_def eq_conv_compare)+ lemma compare_sym: "compare\x\y = (case compare\y\x of LT \ GT | EQ \ EQ | GT \ LT)" by (subst oppOrdering_compare [symmetric]) (simp add: oppOrdering_def) lemma compare_self_neq_LT [simp]: "compare\x\x \ LT" using compare_self_below_EQ [of x] by clarsimp lemma compare_self_neq_GT [simp]: "compare\x\x \ GT" using compare_self_below_EQ [of x] by clarsimp declare compare_self_below_EQ [simp] lemma lt_trans: "lt\x\y = TT \ lt\y\z = TT \ lt\x\z = TT" unfolding lt_eq_TT_iff by (rule compare_LT_trans) lemma compare_GT_iff_LT: "compare\x\y = GT \ compare\y\x = LT" by (cases "compare\x\y", simp_all add: compare_sym [of y x]) lemma compare_GT_trans: "compare\x\y = GT \ compare\y\z = GT \ compare\x\z = GT" unfolding compare_GT_iff_LT by (rule compare_LT_trans) lemma compare_EQ_iff_eq_TT: "compare\x\y = EQ \ eq\x\y = TT" by (cases "compare\x\y") (simp add: is_EQ_def eq_conv_compare)+ lemma compare_EQ_trans: "compare\x\y = EQ \ compare\y\z = EQ \ compare\x\z = EQ" by (blast dest: compare_EQ_dest) lemma le_trans: "le\x\y = TT \ le\y\z = TT \ le\x\z = TT" by (auto dest: eq_TT_dest lt_trans simp: le_iff_lt_or_eq) lemma neg_lt: "neg\(lt\x\y) = le\y\x" by (cases "compare\x\y", simp_all add: le_def lt_def compare_sym [of y x]) lemma neg_le: "neg\(le\x\y) = lt\y\x" by (cases "compare\x\y", simp_all add: le_def lt_def compare_sym [of y x]) subclass Eq_eq proof fix x y show "eq\x\y = eq\y\x" unfolding eq_conv_compare by (cases "compare\x\y", simp_all add: compare_sym [of y x]) show "eq\x\\ = \" unfolding eq_conv_compare by simp show "eq\\\y = \" unfolding eq_conv_compare by simp show "eq\x\x \ FF" unfolding eq_conv_compare by (cases "compare\x\x", simp_all) - { assume "eq\x\y = TT" then show "x = y" - unfolding eq_conv_compare - by (cases "compare\x\y", auto dest: compare_EQ_dest) } + show "x = y" if "eq\x\y = TT" + using that + unfolding eq_conv_compare + by (cases "compare\x\y", auto dest: compare_EQ_dest) qed end text \A combinator for defining Ord instances for datatypes.\ definition thenOrdering :: "Ordering \ Ordering \ Ordering" where "thenOrdering = (\ x y. case x of LT \ LT | EQ \ y | GT \ GT)" lemma thenOrdering_simps [simp]: "thenOrdering\LT\y = LT" "thenOrdering\EQ\y = y" "thenOrdering\GT\y = GT" "thenOrdering\\\y = \" unfolding thenOrdering_def by simp_all lemma thenOrdering_LT_iff [simp]: "thenOrdering\x\y = LT \ x = LT \ x = EQ \ y = LT" by (cases x, simp_all) lemma thenOrdering_EQ_iff [simp]: "thenOrdering\x\y = EQ \ x = EQ \ y = EQ" by (cases x, simp_all) lemma thenOrdering_GT_iff [simp]: "thenOrdering\x\y = GT \ x = GT \ x = EQ \ y = GT" by (cases x, simp_all) lemma thenOrdering_below_EQ_iff [simp]: "thenOrdering\x\y \ EQ \ x \ EQ \ (x = \ \ y \ EQ)" by (cases x) simp_all lemma is_EQ_thenOrdering [simp]: "is_EQ\(thenOrdering\x\y) = (is_EQ\x andalso is_EQ\y)" by (cases x) simp_all lemma oppOrdering_thenOrdering: "oppOrdering\(thenOrdering\x\y) = thenOrdering\(oppOrdering\x)\(oppOrdering\y)" by (cases x) simp_all instantiation lift :: ("{linorder,countable}") Ord_linear begin definition "compare \ (\ (Def x) (Def y). if x < y then LT else if x > y then GT else EQ)" instance proof fix x y z :: "'a lift" show "compare\\\y = \" unfolding compare_lift_def by simp show "compare\x\\ = \" unfolding compare_lift_def by (cases x, simp_all) show "oppOrdering\(compare\x\y) = compare\y\x" unfolding compare_lift_def by (cases x, cases y, simp, simp, cases y, simp, simp add: not_less less_imp_le) - { assume "compare\x\y = EQ" then show "x = y" - unfolding compare_lift_def - by (cases x, cases y, simp, simp, - cases y, simp, simp split: if_splits) } - { assume "compare\x\y = LT" and "compare\y\z = LT" then show "compare\x\z = LT" - unfolding compare_lift_def - by (cases x, simp, cases y, simp, cases z, simp, - auto split: if_splits) } + show "x = y" if "compare\x\y = EQ" + using that + unfolding compare_lift_def + by (cases x, cases y, simp, simp, + cases y, simp, simp split: if_splits) + show "compare\x\z = LT" if "compare\x\y = LT" and "compare\y\z = LT" + using that + unfolding compare_lift_def + by (cases x, simp, cases y, simp, cases z, simp, + auto split: if_splits) show "eq\x\y = is_EQ\(compare\x\y)" unfolding eq_lift_def compare_lift_def by (cases x, simp, cases y, simp, auto) show "compare\x\x \ EQ" unfolding compare_lift_def by (cases x, simp_all) qed end lemma lt_le: "lt\(x::'a::Ord_linear)\y = (le\x\y andalso neq\x\y)" by (cases "compare\x\y") (auto simp: lt_def le_def eq_conv_compare) end diff --git a/thys/HOLCF-Prelude/examples/HLint.thy b/thys/HOLCF-Prelude/examples/HLint.thy --- a/thys/HOLCF-Prelude/examples/HLint.thy +++ b/thys/HOLCF-Prelude/examples/HLint.thy @@ -1,990 +1,989 @@ theory HLint imports "../HOLCF_Prelude" "../List_Comprehension" begin section \HLint\ text \ The tool \texttt{hlint} analyses Haskell code and, based on a data base of rewrite rules, suggests stylistic improvements to it. We verify a number of these rules using our implementation of the Haskell standard library. \ (* -- I/O *) (* putStrLn (show x) ==> print x *) (* mapM_ putChar ==> putStr *) (* hGetChar stdin ==> getChar *) (* hGetLine stdin ==> getLine *) (* hGetContents stdin ==> getContents *) (* hPutChar stdout ==> putChar *) (* hPutStr stdout ==> putStr *) (* hPutStrLn stdout ==> putStrLn *) (* hPrint stdout ==> print *) (* hWaitForInput a 0 ==> hReady a *) (* hPutStrLn a (show b) ==> hPrint a b *) (* hIsEOF stdin ==> isEOF *) (* -- EXIT *) (* exitWith ExitSuccess ==> exitSuccess *) subsection \Ord\ (* not (a == b) ==> a /= b where note = "incorrect if either value is NaN" *) (* not (a /= b) ==> a == b where note = "incorrect if either value is NaN" *) (* not (a > b) ==> a <= b where note = "incorrect if either value is NaN" *) (* not (a >= b) ==> a < b where note = "incorrect if either value is NaN" *) (* not (a < b) ==> a >= b where note = "incorrect if either value is NaN" *) (* not (a <= b) ==> a > b where note = "incorrect if either value is NaN" *) (* compare x y /= GT ==> x <= y *) (* compare x y == LT ==> x < y *) (* compare x y /= LT ==> x >= y *) (* compare x y == GT ==> x > y *) text \@{verbatim \x == a || x == b || x == c ==> x `elem` [a,b,c]\ } \ lemma "(eq\(x::'a::Eq_sym)\a orelse eq\x\b orelse eq\x\c) = elem\x\[a, b, c]" by (auto simp add: eq_sym) text \@{verbatim \ x /= a && x /= b && x /= c ==> x `notElem` [a,b,c]\ } \ lemma "(neq\(x::'a::Eq_sym)\a andalso neq\x\b andalso neq\x\c) = notElem\x\[a, b, c]" by (auto simp add: eq_sym) (* compare (f x) (f y) ==> Data.Ord.comparing f x y -- not that great *) (* on compare f ==> Data.Ord.comparing f -- not that great *) (* -- READ/SHOW *) (* showsPrec 0 x "" ==> show x *) (* readsPrec 0 ==> reads *) (* showsPrec 0 ==> shows *) (* showIntAtBase 16 intToDigit ==> showHex *) (* showIntAtBase 8 intToDigit ==> showOct *) subsection \List\ text \@{verbatim \ concat (map f x) ==> concatMap f x\ } \ lemma "concat\(map\f\x) = concatMap\f\x" by (auto simp add: concatMap_def) text \@{verbatim \ concat [a, b] ==> a ++ b\ } \ lemma "concat\[a, b] = a ++ b" by auto text \@{verbatim \ map f (map g x) ==> map (f . g) x\ } \ lemma "map\f\(map\g\x) = map\(f oo g)\x" by auto text \@{verbatim \ x !! 0 ==> head x\ } \ lemma "x !! 0 = head\x" by (cases x) auto text \@{verbatim \ take n (repeat x) ==> replicate n x\ } \ lemma "take\n\(repeat\x) = replicate\n\x" by (simp add: replicate_def) text \@{verbatim \lemma "head\(reverse\x) = last\x" \ } \ lemma "head\(reverse\x) = last\x" proof (cases "finite_list x") case True then show ?thesis by (induct x rule: reverse_induct) (auto simp add: last_append_singleton) next case False then show ?thesis by (simp add: last_spine_strict reverse_spine_strict) qed text \@{verbatim \ head (drop n x) ==> x !! n where note = "if the index is non-negative"\ } \ lemma assumes "le\0\n \ FF" shows "head\(drop\n\x) = x !! n" proof (cases "le\0\n") assume "le\0\n = FF" with assms show ?thesis.. next assume "le\0\n = TT" then show ?thesis proof (induction arbitrary: x rule: nonneg_Integer_induct) case 0 show ?case by (cases x) auto next case (step i x) from step.hyps have [simp]:"le\i\0 = FF" by (cases i, auto simp add: one_Integer_def zero_Integer_def) from step.hyps have [simp]:"eq\i\0 = FF" by (cases i, auto simp add: one_Integer_def zero_Integer_def) show ?case using step.IH by (cases x)auto qed qed simp text \@{verbatim \ reverse (tail (reverse x)) ==> init x\ } \ lemma "reverse\(tail\(reverse\x)) \ init\x" proof (cases "finite_list x") case True then show ?thesis by (induct x rule: reverse_induct) (auto simp add: init_append_singleton) next case False then show ?thesis by (auto simp add: reverse_spine_strict) qed text \@{verbatim \ take (length x - 1) x ==> init x\ } \ lemma assumes "x \ []" shows "take\(length\x - 1)\x \ init\x" using assms proof (induct x) - case (Cons y ys) + case IH: (Cons y ys) show ?case proof (cases ys) - note IH = Cons case (Cons z zs) show ?thesis using IH by (cases "length\zs") (auto simp: Cons one_Integer_def dest: length_ge_0) qed (auto simp: one_Integer_def) qed auto text \@{verbatim \ foldr (++) [] ==> concat\ } \ lemma foldr_append_concat:"foldr\append\[] = concat" proof (rule cfun_eqI) fix xs :: "[['a]]" show "foldr\append\[]\xs = concat\xs" by (induct xs) auto qed text \@{verbatim \ foldl (++) [] ==> concat\ } \ lemma "foldl\append\[] \ concat" proof (rule cfun_belowI) fix xs :: "[['a]]" show "foldl\append\[]\xs \ concat\xs" by (cases "finite_list xs") (auto simp add: foldr_append_concat foldl_assoc_foldr foldl_spine_strict) qed text \@{verbatim \ span (not . p) ==> break p\ } \ lemma "span\(neg oo p) = break\p" by simp text \@{verbatim \ break (not . p) ==> span p\ } \ lemma "break\(neg oo p) = span\p" by (unfold break.simps) (subst assoc_oo, simp) (* concatMap (++ "\n") ==> unlines *) text \@{verbatim \ or (map p x) ==> any p x\ } \ lemma "the_or\(map\p\x) = any\p\x" by simp text \@{verbatim \ and (map p x) ==> all p x\ } \ lemma "the_and\(map\p\x) = all\p\x" by simp text \@{verbatim \ zipWith (,) ==> zip\ } \ lemma "zipWith\\,\ = zip" by (simp add: zip_def) text \@{verbatim \ zipWith3 (,,) ==> zip3\ } \ lemma "zipWith3\\,,\ = zip3" by (simp add: zip3_def) text \@{verbatim \ length x == 0 ==> null x where note = "increases laziness"\ } \ lemma "eq\(length\x)\0 \ null\x" proof (cases x) case (Cons y ys) then show ?thesis by (cases "length\ys") (auto dest: length_ge_0 simp: zero_Integer_def one_Integer_def) qed simp+ text \@{verbatim \ length x /= 0 ==> not (null x)\ } \ lemma "neq\(length\x)\0 \ neg\(null\x)" proof (cases x) case (Cons y ys) then show ?thesis by (cases "length\ys") (auto dest: length_ge_0 simp: zero_Integer_def one_Integer_def) qed simp+ (* (\x -> [x]) ==> (:[]) *) text \@{verbatim \ map (uncurry f) (zip x y) ==> zipWith f x y\ } \ lemma "map\(uncurry\f)\(zip\x\y) = zipWith\f\x\y" proof (induct x arbitrary: y) case (Cons x xs y) then show ?case by (cases y) auto qed auto text \@{verbatim \ map f (zip x y) ==> zipWith (curry f) x y where _ = isVar f\ } \ lemma "map\f\(zip\x\y) = zipWith\(curry\f)\x\y" proof(induct x arbitrary: y) case (Cons x xs y) then show ?case by (cases y) auto qed auto text \@{verbatim \ not (elem x y) ==> notElem x y\ } \ lemma "neg\(elem\x\y) = notElem\x\y" by (induct y) auto text \@{verbatim \ foldr f z (map g x) ==> foldr (f . g) z x\ } \ lemma "foldr\f\z\(map\g\x) = foldr\(f oo g)\z\x" by (induct x) auto (* x ++ concatMap (' ':) y ==> unwords (x:y) *) (* intercalate " " ==> unwords *) (* concat (intersperse x y) ==> intercalate x y where _ = notEq x " " *) (* concat (intersperse " " x) ==> unwords x *) text \@{verbatim \ null (filter f x) ==> not (any f x)\ } \ lemma "null\(filter\f\x) = neg\(any\f\x)" proof (induct x) case (Cons x xs) then show ?case by (cases "f\x") auto qed auto text \@{verbatim \ filter f x == [] ==> not (any f x)\ } \ lemma "eq\(filter\f\x)\[] = neg\(any\f\x)" proof (induct x) case (Cons x xs) then show ?case by (cases "f\x") auto qed auto text \@{verbatim \ filter f x /= [] ==> any f x\ } \ lemma "neq\(filter\f\x)\[] = any\f\x" proof (induct x) case (Cons x xs) then show ?case by (cases "f\x") auto qed auto text \@{verbatim \ any (== a) ==> elem a\ } \ lemma "any\(\ z. eq\z\a) = elem\a" proof (rule cfun_eqI) fix xs show "any\(\ z. eq\z\a)\xs = elem\a\xs" by (induct xs) auto qed text \@{verbatim \ any ((==) a) ==> elem a\ } \ lemma "any\(eq\(a::'a::Eq_sym)) = elem\a" proof (rule cfun_eqI) fix xs show "any\(eq\a)\xs = elem\a\xs" by (induct xs) (auto simp: eq_sym) qed text \@{verbatim \any (a ==) ==> elem a\ } \ lemma "any\(\ z. eq\(a::'a::Eq_sym)\z) = elem\a" proof (rule cfun_eqI) fix xs show "any\(\ z. eq\a\z)\xs = elem\a\xs" by (induct xs) (auto simp: eq_sym) qed text \@{verbatim \ all (/= a) ==> notElem a\ } \ lemma "all\(\ z. neq\z\(a::'a::Eq_sym)) = notElem\a" proof (rule cfun_eqI) fix xs show "all\(\ z. neq\z\a)\xs = notElem\a\xs" by (induct xs) auto qed text \@{verbatim \ all (a /=) ==> notElem a\ } \ lemma "all\(\ z. neq\(a::'a::Eq_sym)\z) = notElem\a" proof (rule cfun_eqI) fix xs show "all\(\ z. neq\a\z)\xs = notElem\a\xs" by (induct xs) (auto simp: eq_sym) qed (* findIndex ((==) a) ==> elemIndex a *) (* findIndex (a ==) ==> elemIndex a *) (* findIndex (== a) ==> elemIndex a *) (* findIndices ((==) a) ==> elemIndices a *) (* findIndices (a ==) ==> elemIndices a *) (* findIndices (== a) ==> elemIndices a *) (* lookup b (zip l [0..]) ==> elemIndex b l *) subsection \Folds\ (* foldr (>>) (return ()) ==> sequence_ *) text \@{verbatim \ foldr (&&) True ==> and\ } \ lemma "foldr\trand\TT = the_and" by (subst the_and.simps, rule) text \@{verbatim \ foldl (&&) True ==> and\ } \ lemma foldl_to_and:"foldl\trand\TT \ the_and" proof (rule cfun_belowI) fix xs show "foldl\trand\TT\xs \ the_and\xs" by (cases "finite_list xs") (auto simp: foldl_assoc_foldr foldl_spine_strict) qed text \@{verbatim \ foldr1 (&&) ==> and\ } \ lemma "foldr1\trand \ the_and" proof (rule cfun_belowI) fix xs show "foldr1\trand\xs \ the_and\xs" proof (induct xs) case (Cons y ys) then show ?case by (cases ys) (auto elim: monofun_cfun_arg) qed simp+ qed text \@{verbatim \ foldl1 (&&) ==> and\ } \ lemma "foldl1\trand \ the_and" proof (rule cfun_belowI) fix x have "foldl1\trand\x \ foldl\trand\TT\x" by (cases x, auto) also have "... \ the_and\x" by (rule monofun_cfun_fun[OF foldl_to_and]) finally show "foldl1\trand\x \ the_and\x" . qed text \@{verbatim \ foldr (||) False ==> or\ } \ lemma "foldr\tror\FF = the_or" by (subst the_or.simps, rule) text \@{verbatim \ foldl (||) False ==> or\ } \ lemma foldl_to_or: "foldl\tror\FF \ the_or" proof (rule cfun_belowI) fix xs show "foldl\tror\FF\xs \ the_or\xs" by (cases "finite_list xs") (auto simp: foldl_assoc_foldr foldl_spine_strict) qed text \@{verbatim \ foldr1 (||) ==> or\ } \ lemma "foldr1\tror \ the_or" proof (rule cfun_belowI) fix xs show "foldr1\tror\xs \ the_or\xs" proof (induct xs) case (Cons y ys) then show ?case by (cases ys) (auto elim: monofun_cfun_arg) qed simp+ qed text \@{verbatim \ foldl1 (||) ==> or\ } \ lemma "foldl1\tror \ the_or" proof(rule cfun_belowI) fix x have "foldl1\tror\x \ foldl\tror\FF\x" by (cases x, auto) also have "... \ the_or\x" by (rule monofun_cfun_fun[OF foldl_to_or]) finally show "foldl1\tror\x \ the_or\x" . qed (* foldl (+) 0 ==> sum *) (* foldr (+) 0 ==> sum *) (* foldl1 (+) ==> sum *) (* foldr1 (+) ==> sum *) (* foldl ( * ) 1 ==> product *) (* foldr ( * ) 1 ==> product *) (* foldl1 ( * ) ==> product *) (* foldr1 ( * ) ==> product *) (* foldl1 max ==> maximum *) (* foldr1 max ==> maximum *) (* foldl1 min ==> minimum *) (* foldr1 min ==> minimum *) (* foldr mplus mzero ==> msum *) subsection \Function\ text \@{verbatim \ (\x -> x) ==> id\ } \ lemma "(\ x. x) = ID" by (metis ID_def) text \@{verbatim \ (\x y -> x) ==> const\ } \ lemma "(\ x y. x) = const" by (intro cfun_eqI) simp text \@{verbatim \(\(x,y) -> y) ==> fst where _ = notIn x y\ } \ lemma "(\ \x, y\. x) = fst" proof (rule cfun_eqI) fix p show "(case p of \x, y\ \ x) = fst \ p" proof (cases p) case bottom then show ?thesis by simp next case Tuple2 then show ?thesis by simp qed qed text \@{verbatim \(\(x,y) -> y) ==> snd where _ = notIn x y\ } \ lemma "(\ \x, y\. y) = snd" proof (rule cfun_eqI) fix p show "(case p of \x, y\ \ y) = snd \ p" proof (cases p) case bottom then show ?thesis by simp next case Tuple2 then show ?thesis by simp qed qed text \@{verbatim \ (\x y-> f (x,y)) ==> curry f where _ = notIn [x,y] f\ } \ lemma "(\ x y. f\\x, y\) = curry\f" by (auto intro!: cfun_eqI) text \@{verbatim \ (\(x,y) -> f x y) ==> uncurry f where _ = notIn [x,y] f\ } \ lemma "(\ \x, y\. f\x\y) \ uncurry\f" by (rule cfun_belowI, rename_tac x, case_tac x, auto) (* (($) . f) ==> f *) (* (f $) ==> f *) text \@{verbatim \ (\x -> y) ==> const y where _ = isAtom y && notIn x y\ } \ lemma "(\ x. y) = const\y" by (intro cfun_eqI) simp (* flip f x y ==> f y x where _ = isApp original *) lemma "flip\f\x\y = f\y\x" by simp (* (\a b -> o (f a) (f b)) ==> o `Data.Function.on` f *) (* -- CHAR *) (* a >= 'a' && a <= 'z' ==> isAsciiLower a *) (* a >= 'A' && a <= 'Z' ==> isAsciiUpper a *) (* a >= '0' && a <= '9' ==> isDigit a *) (* a >= '0' && a <= '7' ==> isOctDigit a *) (* not (isControl a) ==> isPrint a *) (* isLower a || isUpper a ==> isAlpha a *) (* isAlpha a || isDigit a ==> isAlphaNum a *) subsection \Bool\ text \@{verbatim \ a == True ==> a\ } \ lemma eq_true:"eq\x\TT = x" by (cases x, auto) text \@{verbatim \ a == False ==> not a\ } \ lemma eq_false:"eq\x\FF = neg\x" by (cases x, auto) text \@{verbatim \ (if a then x else x) ==> x where note = "reduces strictness"\ } \ lemma if_equal:"(If a then x else x) \ x" by (cases a, auto) text \@{verbatim \ (if a then True else False) ==> a\ } \ lemma "(If a then TT else FF) = a" by (cases a, auto) text \@{verbatim \ (if a then False else True) ==> not a\ } \ lemma "(If a then FF else TT) = neg\a" by (cases a, auto) text \@{verbatim \ (if a then t else (if b then t else f)) ==> if a || b then t else f\ } \ lemma "(If a then t else (If b then t else f)) = (If a orelse b then t else f)" by (cases a, auto) text \@{verbatim \ (if a then (if b then t else f) else f) ==> if a && b then t else f\ } \ lemma "(If a then (If b then t else f) else f) = (If a andalso b then t else f)" by (cases a, auto) text \@{verbatim \ (if x then True else y) ==> x || y where _ = notEq y False\ } \ lemma "(If x then TT else y) = (x orelse y)" by (cases x, auto) text \@{verbatim \ (if x then y else False) ==> x && y where _ = notEq y True\ } \ lemma "(If x then y else FF) = (x andalso y)" by (cases x, auto) (* case a of {True -> t; False -> f} ==> if a then t else f *) (* case a of {False -> f; True -> t} ==> if a then t else f *) (* case a of {True -> t; _ -> f} ==> if a then t else f *) (* case a of {False -> f; _ -> t} ==> if a then t else f *) text \@{verbatim \ (if c then (True, x) else (False, x)) ==> (c, x) where note = "reduces strictness"\ } \ lemma "(If c then \TT, x\ else \FF, x\) \ \c, x\" by (cases c, auto) text \@{verbatim \ (if c then (False, x) else (True, x)) ==> (not c, x) where note = "reduces strictness"\ } \ lemma "(If c then \FF, x\ else \TT, x\) \ \neg\c, x\" by (cases c, auto) text \@{verbatim \ or [x,y] ==> x || y\ } \ lemma "the_or\[x, y] = (x orelse y)" by (fixrec_simp) text \@{verbatim \ or [x,y,z] ==> x || y || z\ } \ lemma "the_or\[x, y, z] = (x orelse y orelse z)" by (fixrec_simp) text \@{verbatim \ and [x,y] ==> x && y\ } \ lemma "the_and\[x, y] = (x andalso y)" by (fixrec_simp) text \@{verbatim \ and [x,y,z] ==> x && y && z\ } \ lemma "the_and\[x, y, z] = (x andalso y andalso z)" by (fixrec_simp) subsection \Arrow\ (* id *** g ==> second g *) (* f *** id ==> first f *) (* zip (map f x) (map g x) ==> map (f Control.Arrow.&&& g) x *) (* (\(x,y) -> (f x, g y)) ==> f Control.Arrow.*** g where _ = notIn [x,y] [f,g] *) (* (\x -> (f x, g x)) ==> f Control.Arrow.&&& g where _ = notIn x [f,g] *) (* (\(x,y) -> (f x,y)) ==> Control.Arrow.first f where _ = notIn [x,y] f *) (* (\(x,y) -> (x,f y)) ==> Control.Arrow.second f where _ = notIn [x,y] f *) (* (f (fst x), g (snd x)) ==> (f Control.Arrow.*** g) x *) text \@{verbatim \ (fst x, snd x) ==> x\ } \ lemma "x \ \fst\x, snd\x\" by (cases x, auto) (* -- FUNCTOR *) (* fmap f (fmap g x) ==> fmap (f . g) x *) (* fmap id ==> id *) (* -- MONAD *) (* return a >>= f ==> f a *) (* m >>= return ==> m *) (* m >>= return . f ==> Control.Monad.liftM f m -- cannot be fmap, because is in Functor not Monad *) (* (if x then y else return ()) ==> Control.Monad.when x $ _noParen_ y where _ = not (isAtom y) *) (* (if x then y else return ()) ==> Control.Monad.when x y where _ = isAtom y *) (* (if x then return () else y) ==> Control.Monad.unless x $ _noParen_ y where _ = not (isAtom y) *) (* (if x then return () else y) ==> Control.Monad.unless x y where _ = isAtom y *) (* sequence (map f x) ==> mapM f x *) (* sequence_ (map f x) ==> mapM_ f x *) (* flip mapM ==> Control.Monad.forM *) (* flip mapM_ ==> Control.Monad.forM_ *) (* flip forM ==> mapM *) (* flip forM_ ==> mapM_ *) (* when (not x) ==> unless x *) (* x >>= id ==> Control.Monad.join x *) (* liftM f (liftM g x) ==> liftM (f . g) x *) (* a >> return () ==> void a *) (* fmap (const ()) ==> void *) (* flip (>=>) ==> (<=<) *) (* flip (<=<) ==> (>=>) *) (* (\x -> f x >>= g) ==> f Control.Monad.>=> g where _ = notIn x [f,g] *) (* (\x -> f =<< g x) ==> f Control.Monad.<=< g where _ = notIn x [f,g] *) (* a >> forever a ==> forever a *) (* liftM2 id ==> ap *) (* -- MONAD LIST *) (* liftM unzip (mapM f x) ==> Control.Monad.mapAndUnzipM f x *) (* sequence (zipWith f x y) ==> Control.Monad.zipWithM f x y *) (* sequence_ (zipWith f x y) ==> Control.Monad.zipWithM_ f x y *) (* sequence (replicate n x) ==> Control.Monad.replicateM n x *) (* sequence_ (replicate n x) ==> Control.Monad.replicateM_ n x *) (* mapM f (map g x) ==> mapM (f . g) x *) (* mapM_ f (map g x) ==> mapM_ (f . g) x *) (* -- APPLICATIVE / TRAVERSABLE *) (* flip traverse ==> for *) (* flip for ==> traverse *) (* flip traverse_ ==> for_ *) (* flip for_ ==> traverse_ *) (* foldr ( *>) (pure ()) ==> sequenceA_ *) (* foldr (<|>) empty ==> asum *) (* liftA2 (flip ($)) ==> (<**>) *) (* Just <$> a <|> pure Nothing ==> optional a *) (* -- LIST COMP *) (* (if b then [x] else []) ==> [x | b] *) (* [x | x <- y] ==> y where _ = isVar x *) (* -- SEQ *) subsection \Seq\ text \@{verbatim \ x `seq` x ==> x\ } \ lemma "seq\x\x = x" by (simp add: seq_def) (* id $! x ==> x *) (* x `seq` y ==> y where _ = isWHNF x *) (* f $! x ==> f x where _ = isWHNF x *) (* evaluate x ==> return x where _ = isWHNF x *) (* -- MAYBE *) (* maybe x id ==> Data.Maybe.fromMaybe x *) (* maybe False (const True) ==> Data.Maybe.isJust *) (* maybe True (const False) ==> Data.Maybe.isNothing *) (* not (isNothing x) ==> isJust x *) (* not (isJust x) ==> isNothing x *) (* maybe [] (:[]) ==> maybeToList *) (* catMaybes (map f x) ==> mapMaybe f x *) (* (case x of Nothing -> y; Just a -> a) ==> fromMaybe y x *) (* (if isNothing x then y else f (fromJust x)) ==> maybe y f x *) (* (if isJust x then f (fromJust x) else y) ==> maybe y f x *) (* maybe Nothing (Just . f) ==> fmap f *) (* map fromJust . filter isJust ==> Data.Maybe.catMaybes *) (* x == Nothing ==> isNothing x *) (* Nothing == x ==> isNothing x *) (* x /= Nothing ==> Data.Maybe.isJust x *) (* Nothing /= x ==> Data.Maybe.isJust x *) (* concatMap (maybeToList . f) ==> Data.Maybe.mapMaybe f *) (* concatMap maybeToList ==> catMaybes *) (* maybe n Just x ==> Control.Monad.mplus x n *) (* (case x of Just a -> a; Nothing -> y) ==> fromMaybe y x *) (* (if isNothing x then y else fromJust x) ==> fromMaybe y x *) (* (if isJust x then fromJust x else y) ==> fromMaybe y x *) (* isJust x && (fromJust x == y) ==> x == Just y *) (* mapMaybe f (map g x) ==> mapMaybe (f . g) x *) (* fromMaybe a (fmap f x) ==> maybe a f x *) (* [x | Just x <- a] ==> Data.Maybe.catMaybes a *) (* -- EITHER *) (* [a | Left a <- a] ==> lefts a *) (* [a | Right a <- a] ==> rights a *) (* -- INFIX *) (* X.elem x y ==> x `X.elem` y where _ = not (isInfixApp original) && not (isParen result) *) (* X.notElem x y ==> x `X.notElem` y where _ = not (isInfixApp original) && not (isParen result) *) (* X.isInfixOf x y ==> x `X.isInfixOf` y where _ = not (isInfixApp original) && not (isParen result) *) (* X.isSuffixOf x y ==> x `X.isSuffixOf` y where _ = not (isInfixApp original) && not (isParen result) *) (* X.isPrefixOf x y ==> x `X.isPrefixOf` y where _ = not (isInfixApp original) && not (isParen result) *) (* X.union x y ==> x `X.union` y where _ = not (isInfixApp original) && not (isParen result) *) (* X.intersect x y ==> x `X.intersect` y where _ = not (isInfixApp original) && not (isParen result) *) (* -- MATHS *) (* fromIntegral x ==> x where _ = isLitInt x *) (* fromInteger x ==> x where _ = isLitInt x *) (* x + negate y ==> x - y *) (* 0 - x ==> negate x *) (* log y / log x ==> logBase x y *) (* x ** 0.5 ==> sqrt x *) (* sin x / cos x ==> tan x *) (* sinh x / cosh x ==> tanh x *) (* n `rem` 2 == 0 ==> even n *) (* n `rem` 2 /= 0 ==> odd n *) (* not (even x) ==> odd x *) (* not (odd x) ==> even x *) (* x ** 0.5 ==> sqrt x *) (* x ^^ y ==> x ** y where _ = isLitInt y *) (* x ^ 0 ==> 1 *) (* round (x - 0.5) ==> floor x *) (* -- CONCURRENT *) (* mapM_ (writeChan a) ==> writeList2Chan a *) (* -- EXCEPTION *) (* Prelude.catch ==> Control.Exception.catch where note = "Prelude.catch does not catch most exceptions" *) (* flip Control.Exception.catch ==> handle *) (* flip handle ==> Control.Exception.catch *) (* flip (catchJust p) ==> handleJust p *) (* flip (handleJust p) ==> catchJust p *) (* Control.Exception.bracket b (const a) (const t) ==> Control.Exception.bracket_ b a t *) (* Control.Exception.bracket (openFile x y) hClose ==> withFile x y *) (* Control.Exception.bracket (openBinaryFile x y) hClose ==> withBinaryFile x y *) (* throw (ErrorCall a) ==> error a *) (* a `seq` return a ==> Control.Exception.evaluate a *) (* toException NonTermination ==> nonTermination *) (* toException NestedAtomically ==> nestedAtomically *) (* -- WEAK POINTERS *) (* mkWeak a a b ==> mkWeakPtr a b *) (* mkWeak a (a, b) c ==> mkWeakPair a b c *) subsection \Evaluate\ text \@{verbatim \ True && x ==> x\ } \ lemma "(TT andalso x) = x" by auto text \@{verbatim \ False && x ==> False\ } \ lemma "(FF andalso x) = FF" by auto text \@{verbatim \ True || x ==> True\ } \ lemma "(TT orelse x) = TT" by auto text \@{verbatim \ False || x ==> x\ } \ lemma "(FF orelse x) = x" by auto text \@{verbatim \ not True ==> False\ } \ lemma "neg\TT = FF" by auto text \@{verbatim \ not False ==> True\ } \ lemma "neg\FF = TT" by auto (* Nothing >>= k ==> Nothing *) (* either f g (Left x) ==> f x *) (* either f g (Right y) ==> g y *) text \@{verbatim \ fst (x,y) ==> x\ } \ lemma "fst\\x, y\ = x" by auto text \@{verbatim \ snd (x,y) ==> y\ } \ lemma "snd\\x, y\ = y" by auto text \@{verbatim \ f (fst p) (snd p) ==> uncurry f p\ } \ lemma "f\(fst\p)\(snd\p) = uncurry\f\p" by (cases p, auto) text \@{verbatim \ init [x] ==> []\ } \ lemma "init\[x] = []" by auto text \@{verbatim \ null [] ==> True\ } \ lemma "null\[] = TT" by auto text \@{verbatim \ length [] ==> 0\ } \ lemma "length\[] = 0" by auto text \@{verbatim \ foldl f z [] ==> z\ } \ lemma "foldl\f\z\[] = z" by simp text \@{verbatim \ foldr f z [] ==> z\ } \ lemma "foldr\f\z\[] = z" by auto text \@{verbatim \ foldr1 f [x] ==> x\ } \ lemma "foldr1\f\[x] = x" by simp text \@{verbatim \ scanr f z [] ==> [z]\ } \ lemma "scanr\f\z\[] = [z]" by simp text \@{verbatim \ scanr1 f [] ==> []\ } \ lemma "scanr1\f\[] = []" by simp text \@{verbatim \ scanr1 f [x] ==> [x]\ } \ lemma "scanr1\f\[x] = [x]" by simp text \@{verbatim \ take n [] ==> []\ } \ lemma "take\n\[] \ []" by (cases n, auto) text \@{verbatim \ drop n [] ==> []\ } \ lemma "drop\n\[] \ []" by (subst drop.simps) (auto simp: if_equal) text \@{verbatim \ takeWhile p [] ==> []\ } \ lemma "takeWhile\p\[] = []" by (fixrec_simp) text \@{verbatim \ dropWhile p [] ==> []\ } \ lemma "dropWhile\p\[] = []" by (fixrec_simp) text \@{verbatim \ span p [] ==> ([],[])\ } \ lemma "span\p\[] = \[], []\" by (fixrec_simp) (* lines "" ==> [] *) (* unwords [] ==> "" *) (* x - 0 ==> x *) (* x * 1 ==> x *) (* x / 1 ==> x *) text \@{verbatim \ concat [a] ==> a\ } \ lemma "concat\[a] = a" by auto text \@{verbatim \ concat [] ==> []\ } \ lemma "concat\[] = []" by auto text \@{verbatim \ zip [] [] ==> []\ } \ lemma "zip\[]\[] = []" by auto text \@{verbatim \ id x ==> x\ } \ lemma "ID\x = x" by auto text \@{verbatim \ const x y ==> x\ } \ lemma "const\x\y = x" by simp subsection \Complex hints\ text \@{verbatim \ take (length t) s == t ==> t `Data.List.isPrefixOf` s\ } \ lemma fixes t :: "['a::Eq_sym]" shows "eq\(take\(length\t)\s)\t \ isPrefixOf\t\s" by (subst eq_sym) (rule eq_take_length_isPrefixOf) text \@{verbatim \ (take i s == t) ==> _eval_ ((i >= length t) && (t `Data.List.isPrefixOf` s))\ } \ text \The hint is not true in general, as the following two lemmas show:\ lemma assumes "t = []" and "s = x : xs" and "i = 1" shows "\ (eq\(take\i\s)\t \ (le\(length\t)\i andalso isPrefixOf\t\s))" using assms by simp lemma assumes "le\0\i = TT" and "le\i\0 = FF" and "s = \" and "t = []" shows "\ ((le\(length\t)\i andalso isPrefixOf\t\s) \ eq\(take\i\s)\t)" using assms by (subst take.simps) simp (* -- clever hint, but not actually a good idea *) (* (do a <- f; g a) ==> f >>= g *) (* a $$$$ b $$$$ c ==> a . b $$$$$ c *) (* not (a == b) ==> a /= b *) lemma "neg\(eq\a\b) = neq\a\b" by auto text \@{verbatim \not (a /= b) ==> a == b\ } \ lemma "neg\(neq\a\b) = eq\a\b" by auto text \@{verbatim \map id ==> id\ } \ lemma map_id:"map\ID = ID" by (auto simp add: cfun_eq_iff) text \@{verbatim \x == [] ==> null x\ } \ lemma "eq\x\[] = null\x" by (cases x, auto) text \@{verbatim \any id ==> or\ } \ lemma "any\ID = the_or" by (auto simp add:map_id) text \@{verbatim \all id ==> and\ } \ lemma "all\ID = the_and" by (auto simp add:map_id) text \@{verbatim \(if x then False else y) ==> (not x && y)\ } \ lemma "(If x then FF else y) = (neg\x andalso y)" by (cases x, auto) text \@{verbatim \(if x then y else True) ==> (not x || y)\ } \ lemma "(If x then y else TT) = (neg\x orelse y)" by (cases x, auto) text \@{verbatim \not (not x) ==> x\ } \ lemma "neg\(neg\x) = x" by auto text \@{verbatim \(if c then f x else f y) ==> f (if c then x else y)\ } \ lemma "(If c then f\x else f\y) \ f\(If c then x else y)" by (cases c, auto) text \@{verbatim \(\ x -> [x]) ==> (: [])\ } \ lemma "(\ x. [x]) = (\ z. z : [])" by auto text \@{verbatim \True == a ==> a\ } \ lemma "eq\TT\a = a" by (cases a, auto) text \@{verbatim \False == a ==> not a\ } \ lemma "eq\FF\a = neg\a" by (cases a, auto) text \@{verbatim \a /= True ==> not a\ } \ lemma "neq\a\TT = neg\a" by (cases a, auto) text \@{verbatim \a /= False ==> a\ } \ lemma "neq\a\FF = a" by (cases a, auto) text \@{verbatim \True /= a ==> not a\ } \ lemma "neq\TT\a = neg\a" by (cases a, auto) text \@{verbatim \False /= a ==> a\ } \ lemma "neq\FF\a = a" by (cases a, auto) text \@{verbatim \not (isNothing x) ==> isJust x\ } \ lemma "neg\(isNothing\x) = isJust\x" by auto text \@{verbatim \not (isJust x) ==> isNothing x\ } \ lemma "neg\(isJust\x) = isNothing\x" by auto text \@{verbatim \x == Nothing ==> isNothing x\ } \ lemma "eq\x\Nothing = isNothing\x" by (cases x, auto) text \@{verbatim \Nothing == x ==> isNothing x\ } \ lemma "eq\Nothing\x = isNothing\x" by (cases x, auto) text \@{verbatim \x /= Nothing ==> Data.Maybe.isJust x\ } \ lemma "neq\x\Nothing = isJust\x" by (cases x, auto) text \@{verbatim \Nothing /= x ==> Data.Maybe.isJust x\ } \ lemma "neq\Nothing\x = isJust\x" by (cases x, auto) text \@{verbatim \(if isNothing x then y else fromJust x) ==> fromMaybe y x\ } \ lemma "(If isNothing\x then y else fromJust\x) = fromMaybe\y\x" by (cases x, auto) text \@{verbatim \(if isJust x then fromJust x else y) ==> fromMaybe y x\ } \ lemma "(If isJust\x then fromJust\x else y) = fromMaybe\y\x" by (cases x, auto) text \@{verbatim \(isJust x && (fromJust x == y)) ==> x == Just y\ } \ lemma "(isJust\x andalso (eq\(fromJust\x)\y)) = eq\x\(Just\y)" by (cases x, auto) text \@{verbatim \elem True ==> or\ } \ lemma "elem\TT = the_or" proof (rule cfun_eqI) fix xs show "elem\TT\xs = the_or\xs" by (induct xs) (auto simp: eq_true) qed text \@{verbatim \notElem False ==> and\ } \ lemma "notElem\FF = the_and" proof (rule cfun_eqI) fix xs show "notElem\FF\xs = the_and\xs" by (induct xs) (auto simp: eq_false) qed text \@{verbatim \all ((/=) a) ==> notElem a\ } \ lemma "all\(neq\(a::'a::Eq_sym)) = notElem\a" proof (rule cfun_eqI) fix xs show "all\(neq\a)\xs = notElem\a\xs" by (induct xs) (auto simp: eq_sym) qed text \@{verbatim \maybe x id ==> Data.Maybe.fromMaybe x\ } \ lemma "maybe\x\ID = fromMaybe\x" proof (rule cfun_eqI) fix xs show "maybe\x\ID\xs = fromMaybe\x\xs" by (cases xs) auto qed text \@{verbatim \maybe False (const True) ==> Data.Maybe.isJust\ } \ lemma "maybe\FF\(const\TT) = isJust" proof (rule cfun_eqI) fix x :: "'a Maybe" show "maybe\FF\(const\TT)\x = isJust\x" by (cases x) simp+ qed text \@{verbatim \maybe True (const False) ==> Data.Maybe.isNothing\ } \ lemma "maybe\TT\(const\FF) = isNothing" proof (rule cfun_eqI) fix x :: "'a Maybe" show "maybe\TT\(const\FF)\x = isNothing\x" by (cases x) simp+ qed text \@{verbatim \maybe [] (: []) ==> maybeToList\ } \ lemma "maybe\[]\(\ z. z : []) = maybeToList" proof (rule cfun_eqI) fix x :: "'a Maybe" show "maybe\[]\(\ z. z : [])\x = maybeToList\x" by (cases x) simp+ qed text \@{verbatim \catMaybes (map f x) ==> mapMaybe f x\ } \ lemma "catMaybes\(map\f\x) = mapMaybe\f\x" by auto text \@{verbatim \(if isNothing x then y else f (fromJust x)) ==> maybe y f x\ } \ lemma "(If isNothing\x then y else f\(fromJust\x)) = maybe\y\f\x" by (cases x, auto) text \@{verbatim \(if isJust x then f (fromJust x) else y) ==> maybe y f x\ } \ lemma "(If isJust\x then f\(fromJust\x) else y) = maybe\y\f\x" by (cases x, auto) text \@{verbatim \(map fromJust . filter isJust) ==> Data.Maybe.catMaybes\ } \ lemma "(map\fromJust oo filter\isJust) = catMaybes" proof (rule cfun_eqI) fix xs :: "['a Maybe]" show "(map\fromJust oo filter\isJust)\xs = catMaybes\xs" proof (induct xs) case (Cons y ys) then show ?case by (cases y) simp+ qed simp+ qed text \@{verbatim \concatMap (maybeToList . f) ==> Data.Maybe.mapMaybe f\ } \ lemma "concatMap\(maybeToList oo f) = mapMaybe\f" proof (rule cfun_eqI) fix xs show "concatMap\(maybeToList oo f)\xs = mapMaybe\f\xs" by (induct xs) auto qed text \@{verbatim \concatMap maybeToList ==> catMaybes\ } \ lemma "concatMap\maybeToList = catMaybes" by auto text \@{verbatim \mapMaybe f (map g x) ==> mapMaybe (f . g) x\ } \ lemma "mapMaybe\f\(map\g\x) = mapMaybe\(f oo g)\x" by auto text \@{verbatim \(($) . f) ==> f\ } \ lemma "(dollar oo f) = f" by (auto simp add:cfun_eq_iff) text \@{verbatim \(f $) ==> f\ } \ lemma "(\ z. dollar\f\z) = f" by (auto simp add:cfun_eq_iff) text \@{verbatim \(\ a b -> g (f a) (f b)) ==> g `Data.Function.on` f\ } \ lemma "(\ a b. g\(f\a)\(f\b)) = on\g\f" by (auto simp add:cfun_eq_iff) text \@{verbatim \id $! x ==> x\ } \ lemma "dollarBang\ID\x = x" by (auto simp add:seq_def) text \@{verbatim \[x | x <- y] ==> y\ } \ lemma "[x | x <- y] = y" by (induct y, auto) text \@{verbatim \isPrefixOf (reverse x) (reverse y) ==> isSuffixOf x y\ } \ lemma "isPrefixOf\(reverse\x)\(reverse\y) = isSuffixOf\x\y" by auto text \@{verbatim \concat (intersperse x y) ==> intercalate x y\ } \ lemma "concat\(intersperse\x\y) = intercalate\x\y" by auto text \@{verbatim \x `seq` y ==> y\ } \ lemma assumes "x \ \" shows "seq\x\y = y" using assms by (simp add: seq_def) text \@{verbatim \f $! x ==> f x\ } \ lemma assumes "x \ \" shows "dollarBang\f\x = f\x" using assms by (simp add: seq_def) text \@{verbatim \maybe (f x) (f . g) ==> (f . maybe x g)\ } \ lemma "maybe\(f\x)\(f oo g) \ (f oo maybe\x\g)" proof (rule cfun_belowI) fix y show "maybe\(f\x)\(f oo g)\y \ (f oo maybe\x\g)\y" by (cases y) auto qed end