Theory HOLCF_Main
section ‹Initial Setup for HOLCF-Prelude›
theory HOLCF_Main
imports
HOLCF
"HOLCF-Library.Int_Discrete"
"HOL-Library.Adhoc_Overloading"
begin
text ‹
All theories from the Isabelle distribution which are used
anywhere in the HOLCF-Prelude library must be imported via this file.
This way, we only have to hide constant names and syntax in one place.
›
hide_type (open) list
hide_const (open)
List.append List.concat List.Cons List.distinct List.filter List.last
List.foldr List.foldl List.length List.lists List.map List.Nil List.nth
List.partition List.replicate List.set List.take List.upto List.zip
Orderings.less Product_Type.fst Product_Type.snd
no_notation Map.map_add (infixl "++" 100)
no_notation List.upto ("(1[_../_])")
no_notation
Rings.divide (infixl "div" 70) and
Rings.modulo (infixl "mod" 70)
no_notation
Set.member ("(:)") and
Set.member ("(_/ : _)" [51, 51] 50)
no_translations
"[x, xs]" == "x # [xs]"
"[x]" == "x # []"
no_syntax
"_list" :: "args ⇒ 'a List.list" ("[(_)]")
no_notation
List.Nil ("[]")
no_syntax "_bracket" :: "types ⇒ type ⇒ type" ("([_]/ => _)" [0, 0] 0)
no_syntax "_bracket" :: "types ⇒ type ⇒ type" ("([_]/ ⇒ _)" [0, 0] 0)
no_translations
"[x<-xs . P]" == "CONST List.filter (%x. P) xs"
no_syntax (ASCII)
"_filter" :: "pttrn ⇒ 'a List.list ⇒ bool ⇒ 'a List.list" ("(1[_<-_./ _])")
no_syntax
"_filter" :: "pttrn ⇒ 'a List.list ⇒ bool ⇒ 'a List.list" ("(1[_←_ ./ _])")
text ‹Declarations that belong in HOLCF/Tr.thy:›
declare trE [cases type: tr]
declare tr_induct [induct type: tr]
end
Theory Type_Classes
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"
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) }
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 "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
Theory Numeral_Cpo
section ‹Cpo for Numerals›
theory Numeral_Cpo
imports HOLCF_Main
begin
class plus_cpo = plus + cpo +
assumes cont_plus1: "cont (λx::'a::{plus,cpo}. x + y)"
assumes cont_plus2: "cont (λy::'a::{plus,cpo}. x + y)"
begin
abbreviation plus_section :: "'a → 'a → 'a" ("'(+')") where
"(+) ≡ Λ x y. x + y"
abbreviation plus_section_left :: "'a ⇒ 'a → 'a" ("'(_+')") where
"(x+) ≡ Λ y. x + y"
abbreviation plus_section_right :: "'a ⇒ 'a → 'a" ("'(+_')") where
"(+y) ≡ Λ x. x + y"
end
class minus_cpo = minus + cpo +
assumes cont_minus1: "cont (λx::'a::{minus,cpo}. x - y)"
assumes cont_minus2: "cont (λy::'a::{minus,cpo}. x - y)"
begin
abbreviation minus_section :: "'a → 'a → 'a" ("'(-')") where
"(-) ≡ Λ x y. x - y"
abbreviation minus_section_left :: "'a ⇒ 'a → 'a" ("'(_-')") where
"(x-) ≡ Λ y. x - y"
abbreviation minus_section_right :: "'a ⇒ 'a → 'a" ("'(-_')") where
"(-y) ≡ Λ x. x - y"
end
class times_cpo = times + cpo +
assumes cont_times1: "cont (λx::'a::{times,cpo}. x * y)"
assumes cont_times2: "cont (λy::'a::{times,cpo}. x * y)"
begin
end
lemma cont2cont_plus [simp, cont2cont]:
assumes "cont (λx. f x)" and "cont (λx. g x)"
shows "cont (λx. f x + g x :: 'a::plus_cpo)"
apply (rule cont_apply [OF assms(1) cont_plus1])
apply (rule cont_apply [OF assms(2) cont_plus2])
apply (rule cont_const)
done
lemma cont2cont_minus [simp, cont2cont]:
assumes "cont (λx. f x)" and "cont (λx. g x)"
shows "cont (λx. f x - g x :: 'a::minus_cpo)"
apply (rule cont_apply [OF assms(1) cont_minus1])
apply (rule cont_apply [OF assms(2) cont_minus2])
apply (rule cont_const)
done
lemma cont2cont_times [simp, cont2cont]:
assumes "cont (λx. f x)" and "cont (λx. g x)"
shows "cont (λx. f x * g x :: 'a::times_cpo)"
apply (rule cont_apply [OF assms(1) cont_times1])
apply (rule cont_apply [OF assms(2) cont_times2])
apply (rule cont_const)
done
instantiation u :: ("{zero,cpo}") zero
begin
definition "zero_u = up⋅(0::'a)"
instance ..
end
instantiation u :: ("{one,cpo}") one
begin
definition "one_u = up⋅(1::'a)"
instance ..
end
instantiation u :: (plus_cpo) plus
begin
definition "plus_u x y = (Λ(up⋅a) (up⋅b). up⋅(a + b))⋅x⋅y" for x y :: "'a⇩⊥"
instance ..
end
instantiation u :: (minus_cpo) minus
begin
definition "minus_u x y = (Λ(up⋅a) (up⋅b). up⋅(a - b))⋅x⋅y" for x y :: "'a⇩⊥"
instance ..
end
instantiation u :: (times_cpo) times
begin
definition "times_u x y = (Λ(up⋅a) (up⋅b). up⋅(a * b))⋅x⋅y" for x y :: "'a⇩⊥"
instance ..
end
lemma plus_u_strict [simp]:
fixes x :: "_ u" shows "x + ⊥ = ⊥" and "⊥ + x = ⊥"
unfolding plus_u_def by (cases x, simp, simp)+
lemma minus_u_strict [simp]:
fixes x :: "_ u" shows "x - ⊥ = ⊥" and "⊥ - x = ⊥"
unfolding minus_u_def by (cases x, simp_all)+
lemma times_u_strict [simp]:
fixes x :: "_ u" shows "x * ⊥ = ⊥" and "⊥ * x = ⊥"
unfolding times_u_def by (cases x, simp_all)+
lemma plus_up_up [simp]: "up⋅x + up⋅y = up⋅(x + y)"
unfolding plus_u_def by simp
lemma minus_up_up [simp]: "up⋅x - up⋅y = up⋅(x - y)"
unfolding minus_u_def by simp
lemma times_up_up [simp]: "up⋅x * up⋅y = up⋅(x * y)"
unfolding times_u_def by simp
instance u :: (plus_cpo) plus_cpo
by standard (simp_all add: plus_u_def)
instance u :: (minus_cpo) minus_cpo
by standard (simp_all add: minus_u_def)
instance u :: (times_cpo) times_cpo
by standard (simp_all add: times_u_def)
instance u :: ("{semigroup_add,plus_cpo}") semigroup_add
proof
fix a b c :: "'a u"
show "(a + b) + c = a + (b + c)"
unfolding plus_u_def
by (cases a; cases b; cases c) (simp_all add: add.assoc)
qed
instance u :: ("{ab_semigroup_add,plus_cpo}") ab_semigroup_add
proof
fix a b :: "'a u"
show "a + b = b + a"
by (cases a; cases b) (simp_all add: add.commute)
qed
instance u :: ("{monoid_add,plus_cpo}") monoid_add
proof
fix a :: "'a u"
show "0 + a = a"
unfolding zero_u_def by (cases a) simp_all
show "a + 0 = a"
unfolding zero_u_def by (cases a) simp_all
qed
instance u :: ("{comm_monoid_add,plus_cpo}") comm_monoid_add
proof
fix a :: "'a u"
show "0 + a = a"
unfolding zero_u_def by (cases a) simp_all
qed
instance u :: ("{numeral, plus_cpo}") numeral ..
instance int :: plus_cpo
by standard simp_all
instance int :: minus_cpo
by standard simp_all
end
Theory Data_Function
section ‹Data: Functions›
theory Data_Function
imports HOLCF_Main
begin
fixrec flip :: "('a -> 'b -> 'c) -> 'b -> 'a -> 'c" where
"flip⋅f⋅x⋅y = f⋅y⋅x"
fixrec const :: "'a → 'b → 'a" where
"const⋅x⋅_ = x"
fixrec dollar :: "('a -> 'b) -> 'a -> 'b" where
"dollar⋅f⋅x = f⋅x"
fixrec dollarBang :: "('a -> 'b) -> 'a -> 'b" where
"dollarBang⋅f⋅x = seq⋅x⋅(f⋅x)"
fixrec on :: "('b -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'a -> 'c" where
"on⋅g⋅f⋅x⋅y = g⋅(f⋅x)⋅(f⋅y)"
end
Theory Data_Bool
section ‹Data: Bool›
theory Data_Bool
imports Type_Classes
begin
subsection ‹Class instances›
text ‹Eq›
lemma eq_eqI[case_names bottomLTR bottomRTL LTR RTL]:
"(x = ⊥ ⟹ y = ⊥) ⟹ (y = ⊥ ⟹ x = ⊥) ⟹ (x = TT ⟹ y = TT) ⟹ (y = TT ⟹ x = TT) ⟹ x = y"
by (metis Exh_tr)
lemma eq_tr_simps [simp]:
shows "eq⋅TT⋅TT = TT" and "eq⋅TT⋅FF = FF"
and "eq⋅FF⋅TT = FF" and "eq⋅FF⋅FF = TT"
unfolding TT_def FF_def eq_lift_def by simp_all
text ‹Ord›
lemma compare_tr_simps [simp]:
"compare⋅FF⋅FF = EQ"
"compare⋅FF⋅TT = LT"
"compare⋅TT⋅FF = GT"
"compare⋅TT⋅TT = EQ"
unfolding TT_def FF_def compare_lift_def
by simp_all
subsection ‹Lemmas›
lemma andalso_eq_TT_iff [simp]:
"(x andalso y) = TT ⟷ x = TT ∧ y = TT"
by (cases x, simp_all)
lemma andalso_eq_FF_iff [simp]:
"(x andalso y) = FF ⟷ x = FF ∨ (x = TT ∧ y = FF)"
by (cases x, simp_all)
lemma andalso_eq_bottom_iff [simp]:
"(x andalso y) = ⊥ ⟷ x = ⊥ ∨ (x = TT ∧ y = ⊥)"
by (cases x, simp_all)
lemma orelse_eq_FF_iff [simp]:
"(x orelse y) = FF ⟷ x = FF ∧ y = FF"
by (cases x, simp_all)
lemma orelse_assoc [simp]:
"((x orelse y) orelse z) = (x orelse y orelse z)"
by (cases x) auto
lemma andalso_assoc [simp]:
"((x andalso y) andalso z) = (x andalso y andalso z)"
by (cases x) auto
lemma neg_orelse [simp]:
"neg⋅(x orelse y) = (neg⋅x andalso neg⋅y)"
by (cases x) auto
lemma neg_andalso [simp]:
"neg⋅(x andalso y) = (neg⋅x orelse neg⋅y)"
by (cases x) auto
text ‹Not suitable as default simp rules, because they cause the
simplifier to loop:›
lemma neg_eq_simps:
"neg⋅x = TT ⟹ x = FF"
"neg⋅x = FF ⟹ x = TT"
"neg⋅x = ⊥ ⟹ x = ⊥"
by (cases x, simp_all)+
lemma neg_eq_TT_iff [simp]: "neg⋅x = TT ⟷ x = FF"
by (cases x, simp_all)+
lemma neg_eq_FF_iff [simp]: "neg⋅x = FF ⟷ x = TT"
by (cases x, simp_all)+
lemma neg_eq_bottom_iff [simp]: "neg⋅x = ⊥ ⟷ x = ⊥"
by (cases x, simp_all)+
lemma neg_eq [simp]:
"neg⋅x = neg⋅y ⟷ x = y"
by (cases y, simp_all)
lemma neg_neg [simp]:
"neg⋅(neg⋅x) = x"
by (cases x, auto)
lemma neg_comp_neg [simp]:
"neg oo neg = ID"
by (metis cfun_eqI cfcomp2 neg_neg ID1)
end
Theory Data_Tuple
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) }
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) }
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 "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) }
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) }
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)
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 elim!: compare_LT_trans)
done }
show "compare⋅x⋅x ⊑ EQ"
by (cases x, simp_all)
qed
end
Theory Data_Integer
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 "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
Theory Data_List
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)
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)"
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)))"
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) }
moreover
{ assume "n < m" then have "?P m n" 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
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)
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 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]:
"(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]:
"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"
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
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"
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
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 }
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"
by (induct a "map⋅f⋅xs" arbitrary: xs)
(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
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
Theory Data_Maybe
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"
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 }
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
Theory Definedness
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
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
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:
"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:
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
Theory List_Comprehension
section ‹List Comprehension›
theory List_Comprehension
imports Data_List
begin
no_notation
disj (infixr "|" 30)
nonterminal llc_qual and llc_quals
syntax
"_llc" :: "'a ⇒ llc_qual ⇒ llc_quals ⇒ ['a]" ("[_ | __")
"_llc_gen" :: "'a ⇒ ['a] ⇒ llc_qual" ("_ <- _")
"_llc_guard" :: "tr ⇒ llc_qual" ("_")
"_llc_let" :: "letbinds ⇒ llc_qual" ("let _")
"_llc_quals" :: "llc_qual ⇒ llc_quals ⇒ llc_quals" (", __")
"_llc_end" :: "llc_quals" ("]")
"_llc_abs" :: "'a ⇒ ['a] ⇒ ['a]"
translations
"[e | p <- xs]" => "CONST concatMap⋅(_llc_abs p [e])⋅xs"
"_llc e (_llc_gen p xs) (_llc_quals q qs)"
=> "CONST concatMap⋅(_llc_abs p (_llc e q qs))⋅xs"
"[e | b]" => "If b then [e] else []"
"_llc e (_llc_guard b) (_llc_quals q qs)"
=> "If b then (_llc e q qs) else []"
"_llc e (_llc_let b) (_llc_quals q qs)"
=> "_Let b (_llc e q qs)"
parse_translation ‹
let open HOLCF_Library in
let
val NilC = Syntax.const @{const_syntax "Nil"};
fun Lam x = Syntax.const @{const_syntax "Abs_cfun"} $ x;
fun fresh_var ts ctxt =
let
val ctxt' = fold Variable.declare_term ts ctxt
in
singleton (Variable.variant_frees ctxt' []) ("x", dummyT)
end
fun pat_tr ctxt p e =
let
val x = Free (fresh_var [p, e] ctxt);
val case1 = Syntax.const @{syntax_const "_case1"} $ p $ e;
val case2 =
Syntax.const @{syntax_const "_case1"} $
Syntax.const @{const_syntax Pure.dummy_pattern} $ NilC;
val cs = Syntax.const @{syntax_const "_case2"} $ case1 $ case2;
in
Syntax_Trans.abs_tr [x, Case_Translation.case_tr false ctxt [x, cs]]
|> Lam
end
fun abs_tr ctxt [p, e] =
(case Term_Position.strip_positions p of
Free (s, T) => Lam (Syntax_Trans.abs_tr [p, e])
| _ => pat_tr ctxt p e)
in [(@{syntax_const "_llc_abs"}, abs_tr)] end
end
›
lemma concatMap_singleton [simp]:
"concatMap⋅(Λ x. [f⋅x])⋅xs = map⋅f⋅xs"
by (induct xs) simp_all
lemma listcompr_filter [simp]:
"[x | x <- xs, P⋅x] = filter⋅P⋅xs"
proof (induct xs)
case (Cons a xs)
then show ?case by (cases "P⋅a"; simp)
qed simp_all
lemma "[y | let y = x*2; z = y, x <- xs] = A"
apply simp
oops
end
Theory Num_Class
section ‹The Num Class›
theory Num_Class
imports
Type_Classes
Data_Integer
Data_Tuple
begin
subsection ‹Num class›
class Num_syn =
Eq +
plus +
minus +
times +
zero +
one +
fixes negate :: "'a → 'a"
and abs :: "'a → 'a"
and signum :: "'a → 'a"
and fromInteger :: "Integer → 'a"
class Num = Num_syn + plus_cpo + minus_cpo + times_cpo
class Num_strict = Num +
assumes plus_strict[simp]:
"x + ⊥ = (⊥::'a::Num)"
"⊥ + x = ⊥"
assumes minus_strict[simp]:
"x - ⊥ = ⊥"
"⊥ - x = ⊥"
assumes mult_strict[simp]:
"x * ⊥ = ⊥"
"⊥ * x = ⊥"
assumes negate_strict[simp]:
"negate⋅⊥ = ⊥"
assumes abs_strict[simp]:
"abs⋅⊥ = ⊥"
assumes signum_strict[simp]:
"signum⋅⊥ = ⊥"
assumes fromInteger_strict[simp]:
"fromInteger⋅⊥ = ⊥"
class Num_faithful =
Num_syn +
assumes abs_signum_eq: "(eq⋅((abs⋅x) * (signum⋅x))⋅(x::'a::{Num_syn})) ⊑ TT"
class Integral =
Num +
fixes div mod :: "'a → 'a → ('a::Num)"
fixes toInteger :: "'a → Integer"
begin
fixrec divMod :: "'a → 'a → ⟨'a, 'a⟩" where "divMod⋅x⋅y = ⟨div⋅x⋅y, mod⋅x⋅y⟩"
fixrec even :: "'a → tr" where "even⋅x = eq⋅(div⋅x⋅(fromInteger⋅2))⋅0"
fixrec odd :: "'a → tr" where "odd⋅x = neg⋅(even⋅x)"
end
class Integral_strict = Integral +
assumes div_strict[simp]:
"div⋅x⋅⊥ = (⊥::'a::Integral)"
"div⋅⊥⋅x = ⊥"
assumes mod_strict[simp]:
"mod⋅x⋅⊥ = ⊥"
"mod⋅⊥⋅x = ⊥"
assumes toInteger_strict[simp]:
"toInteger⋅⊥ = ⊥"
class Integral_faithful =
Integral +
Num_faithful +
assumes "eq⋅y⋅0 = FF ⟹ div⋅x⋅y * y + mod⋅x⋅y = (x::'a::{Integral})"
subsection ‹Instances for Integer›
instantiation Integer :: Num_syn
begin
definition "negate = (Λ (MkI⋅x). MkI⋅(uminus x))"
definition "abs = (Λ (MkI⋅x) . MkI⋅(¦x¦))"
definition "signum = (Λ (MkI⋅x) . MkI⋅(sgn x))"
definition "fromInteger = (Λ x. x)"
instance..
end
instance Integer :: Num
by standard
instance Integer :: Num_faithful
apply standard
apply (rename_tac x, case_tac x)
apply simp
apply (simp add: signum_Integer_def abs_Integer_def)
apply (metis mult.commute mult_sgn_abs)
done
instance Integer :: Num_strict
apply standard
unfolding signum_Integer_def abs_Integer_def negate_Integer_def fromInteger_Integer_def
by simp_all
instantiation Integer :: Integral
begin
definition "div = (Λ (MkI⋅x) (MkI⋅y). MkI⋅(Rings.divide x y))"
definition "mod = (Λ (MkI⋅x) (MkI⋅y). MkI⋅(Rings.modulo x y))"
definition "toInteger = (Λ x. x)"
instance ..
end
instance Integer :: Integral_strict
apply standard
unfolding div_Integer_def mod_Integer_def toInteger_Integer_def
apply simp_all
apply (rename_tac x, case_tac x, simp, simp)+
done
instance Integer :: Integral_faithful
apply standard
unfolding div_Integer_def mod_Integer_def
apply (rename_tac y x)
apply (case_tac y, simp)
apply (case_tac x, simp)
apply simp
done
lemma Integer_Integral_simps[simp]:
"div⋅(MkI⋅x)⋅(MkI⋅y) = MkI⋅(Rings.divide x y)"
"mod⋅(MkI⋅x)⋅(MkI⋅y) = MkI⋅(Rings.modulo x y)"
"fromInteger⋅i = i"
unfolding mod_Integer_def div_Integer_def fromInteger_Integer_def by simp_all
end
Theory Fibs
theory "Fibs"
imports
"../HOLCF_Prelude"
"../Definedness"
begin
section ‹Fibonacci sequence›
text ‹
In this example, we show that the self-recursive lazy definition of the
fibonacci sequence is actually defined and correct.
›
fixrec fibs :: "[Integer]" where
[simp del]: "fibs = 0 : 1 : zipWith⋅(+)⋅fibs⋅(tail⋅fibs)"
fun fib :: "int ⇒ int" where
"fib n = (if n ≤ 0 then 0 else if n = 1 then 1 else fib (n - 1) + fib (n - 2))"
declare fib.simps [simp del]
lemma fibs_0 [simp]:
"fibs !! 0 = 0"
by (subst fibs.simps) simp
lemma fibs_1 [simp]:
"fibs !! 1 = 1"
by (subst fibs.simps) simp
text ‹And the proof that @{term "fibs !! i"} is defined and the fibs value.›
lemma [simp]:"-1 + ⟦i⟧ = ⟦ i ⟧ - 1" by simp
lemma [simp]:"-2 + ⟦i⟧ = ⟦ i ⟧ - 2" by simp
lemma nth_fibs:
assumes "defined i" and "⟦ i ⟧ ≥ 0" shows "defined (fibs !! i)" and "⟦ fibs !! i ⟧ = fib ⟦ i ⟧"
using assms
proof(induction i rule:nonneg_full_Int_induct)
case (Suc i)
case 1
with Suc show ?case
apply (cases "⟦i⟧ = 0")
apply (subst fibs.simps, (subst fib.simps)?, simp add: nth_zipWith nth_tail)
apply (cases "⟦i⟧ = 1")
apply (subst fibs.simps, (subst fib.simps)?, simp add: nth_zipWith nth_tail)
apply (subst fibs.simps, (subst fib.simps)?, simp add: nth_zipWith nth_tail)
done
qed (subst fibs.simps, (subst fib.simps)?, simp add: nth_zipWith nth_tail)+
end
Theory Sieve_Primes
theory Sieve_Primes
imports
"HOL-Computational_Algebra.Primes"
"../Num_Class"
"../HOLCF_Prelude"
begin
section ‹The Sieve of Eratosthenes›
declare [[coercion int]]
declare [[coercion_enabled]]
text ‹
This example proves that the well-known Haskell two-liner that lazily
calculates the list of all primes does indeed do so. This proof is using
coinduction.
›
text ‹
We need to hide some constants again since we imported something from HOL
not via @{theory "HOLCF-Prelude.HOLCF_Main"}.
›
no_notation
Rings.divide (infixl "div" 70) and
Rings.modulo (infixl "mod" 70)
no_notation
Set.member ("(:)") and
Set.member ("(_/ : _)" [51, 51] 50)
text ‹This is the implementation. We also need a modulus operator.›
fixrec sieve :: "[Integer] → [Integer]" where
"sieve⋅(p : xs) = p : (sieve⋅(filter⋅(Λ x. neg⋅(eq⋅(mod⋅x⋅p)⋅0))⋅xs))"
fixrec primes :: "[Integer]" where
"primes = sieve⋅[2..]"
text ‹Simplification rules for modI:›
definition MkI' :: "int ⇒ Integer" where
"MkI' x = MkI⋅x"
lemma MkI'_simps [simp]:
shows "MkI' 0 = 0" and "MkI' 1 = 1" and "MkI' (numeral k) = numeral k"
unfolding MkI'_def zero_Integer_def one_Integer_def numeral_Integer_eq
by rule+
lemma modI_numeral_numeral [simp]:
"mod⋅(numeral i)⋅(numeral j) = MkI' (Rings.modulo (numeral i) (numeral j))"
unfolding numeral_Integer_eq mod_Integer_def MkI'_def by simp
text ‹Some lemmas demonstrating evaluation of our list:›
lemma "primes !! 0 = 2"
unfolding primes.simps
apply (simp only: enumFrom_intsFrom_conv)
apply (subst intsFrom.simps)
apply simp
done
lemma "primes !! 1 = 3"
unfolding primes.simps
apply (simp only: enumFrom_intsFrom_conv)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply simp
done
lemma "primes !! 2 = 5"
unfolding primes.simps
apply (simp only: enumFrom_intsFrom_conv)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply simp
done
lemma "primes !! 3 = 7"
unfolding primes.simps
apply (simp only: enumFrom_intsFrom_conv)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply (subst intsFrom.simps)
apply (simp del: filter_FF filter_TT)
done
text ‹Auxiliary lemmas about prime numbers›
lemma find_next_prime_nat:
fixes n :: nat
assumes "prime n"
shows "∃ n'. n' > n ∧ prime n' ∧ (∀k. n < k ⟶ k < n' ⟶ ¬ prime k)"
using ex_least_nat_le[of "λ k . k > n ∧ prime k"]
by (metis bigger_prime not_prime_0)
text ‹Simplification for andalso:›
lemma andAlso_Def[simp]: "((Def x) andalso (Def y)) = Def (x ∧ y)"
by (metis Def_bool2 Def_bool4 andalso_thms(1) andalso_thms(2))
text ‹This defines the bisimulation and proves it to be a list bisimulation.›
definition prim_bisim:
"prim_bisim x1 x2 = (∃ n . prime n ∧
x1 = sieve⋅(filter⋅(Λ (MkI⋅i). Def ((∀d. d > 1 ⟶ d < n ⟶ ¬ (d dvd i))))⋅[MkI⋅n..]) ∧
x2 = filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅n..])"
lemma prim_bisim_is_bisim: "list_bisim prim_bisim"
proof -
{
fix xs ys
assume "prim_bisim xs ys"
then obtain n :: nat where
"prime n" and
"n > 1" and
"xs = sieve⋅(filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < n ⟶ ¬ (d dvd i))))⋅[MkI⋅n..])" (is "_ = sieve⋅?xs") and
"ys = filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅n..]"
proof -
assume a1: "⋀n. ⟦prime n; 1 < n; xs = sieve⋅ (Data_List.filter⋅ (Λ (MkI⋅i). Def (∀d>1. d < int n ⟶ ¬ d dvd i))⋅ [MkI⋅(int n)..]); ys = Data_List.filter⋅ (Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅ [MkI⋅(int n)..]⟧ ⟹ thesis"
obtain ii where
f2: "∀is isa. (¬ prim_bisim is isa ∨ prime (ii is isa) ∧ is = sieve⋅ (Data_List.filter⋅ (Λ (MkI⋅i). Def (∀ia>1. ia < ii is isa ⟶ ¬ ia dvd i))⋅ [MkI⋅(ii is isa)..]) ∧ isa = Data_List.filter⋅ (Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅ [MkI⋅(ii is isa)..]) ∧ ((∀i. ¬ prime i ∨ is ≠ sieve⋅ (Data_List.filter⋅ (Λ (MkI⋅ia). Def (∀ib>1. ib < i ⟶ ¬ ib dvd ia))⋅ [MkI⋅i..]) ∨ isa ≠ Data_List.filter⋅ (Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅ [MkI⋅i..]) ∨ prim_bisim is isa)"
using prim_bisim by moura
then have f3: "prime (ii xs ys)"
using ‹prim_bisim xs ys› by blast
then obtain nn :: "int ⇒ nat" where
f4: "int (nn (ii xs ys)) = ii xs ys"
by (metis (no_types) prime_gt_0_int zero_less_imp_eq_int)
then have "prime (nn (ii xs ys))"
using f3 by (metis (no_types) prime_nat_int_transfer)
then show ?thesis
using f4 f2 a1 ‹prim_bisim xs ys› prime_gt_1_nat by presburger
qed
obtain n' where "n' > n" and "prime n'" and not_prime: "∀k. n < k ⟶ k < n' ⟶ ¬ prime k"
using find_next_prime_nat[OF ‹prime n›] by auto
{
fix k :: int
assume "n < k" and "k < n'"
have "k > 1" using ‹n < k› ‹n > 1› by auto
then obtain k' :: nat where "k = int k'" by (cases k) auto
then obtain p where "prime p" and "p dvd k"
using ‹k > 1› ‹k = int k'›
by (metis (full_types) less_numeral_extra(4) of_nat_1 of_nat_dvd_iff prime_factor_nat prime_nat_int_transfer)
then have "p < n'" using ‹k < n'› ‹k > 1›
using zdvd_imp_le [of p k] by simp
then have "p ≤ n" using ‹prime p› not_prime
using not_le prime_gt_0_int zero_less_imp_eq_int
by (metis of_nat_less_iff prime_nat_int_transfer)
then have "∃d::int>1. d ≤ n ∧ d dvd k" using ‹p dvd k› ‹prime p› of_nat_le_iff prime_gt_1_nat
prime_gt_1_int by auto
}
then have between_have_divisors: "⋀k::int. n < k ⟹ k < n' ⟹ ∃d::int>1. d ≤ n ∧ d dvd k".
{
fix i
{
assume small: "∀d::int>1. d ≤ n ⟶ ¬ d dvd i"
fix d
assume "1 < d" and "d dvd i" and "d < n'"
with small have "d > n" by auto
obtain d'::int where "d' > 1" and "d' ≤ n" and "d' dvd d" using between_have_divisors[OF ‹n < d› ‹d < n'›] by auto
with ‹d dvd i› small have False by (metis (full_types) dvd_trans)
}
then have "(∀d::int. d > 1 ⟶ d ≤ n ⟶ ¬ (d dvd i)) = (∀d::int. d > 1 ⟶ d < n' ⟶ ¬ (d dvd i))"
using ‹n' > n› by auto
}
then have between_not_relvant: "⋀ i. (∀d::int. d > 1 ⟶ d ≤ n ⟶ ¬ (d dvd i)) = (∀d::int. d > 1 ⟶ d < n' ⟶ ¬ (d dvd i))" .
from ‹prime n›
have "∀d::int >1. d < n ⟶ ¬ d dvd n"
unfolding prime_int_altdef using int_one_le_iff_zero_less le_less
by (simp add: prime_int_not_dvd)
then
obtain xs' where "?xs = (MkI⋅n) : xs'" and "xs' = filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < n ⟶ ¬ (d dvd i))))⋅[MkI⋅(n+1)..]"
by (subst (asm) intsFrom.simps[unfolded enumFrom_intsFrom_conv[symmetric]], simp add: one_Integer_def TT_def[symmetric] add.commute)
{
have "filter⋅(Λ x. neg⋅(eq⋅(mod⋅x⋅(MkI⋅n))⋅0))⋅(filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < n ⟶ ¬ (d dvd i))))⋅[MkI⋅(n+1)..])
= filter⋅(Λ (MkI⋅x). Def (¬ n dvd x))⋅(filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < n ⟶ ¬ (d dvd i))))⋅[MkI⋅(n+1)..])"
apply (rule filter_cong[rule_format])
apply (rename_tac x, case_tac x)
apply (simp)
apply (auto simp add: zero_Integer_def)
apply (rule FF_def)
apply (simp add: TT_def)
by (metis dvd_eq_mod_eq_0)
also have "... = filter⋅(Λ (MkI⋅i). Def ((¬ n dvd i) ∧ (∀d::int. d > 1 ⟶ d < n ⟶ ¬ (d dvd i))))⋅[MkI⋅(n+1)..]"
by (auto intro!: filter_cong[rule_format])
also have "... = filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d ≤ n ⟶ ¬ (d dvd i))))⋅[MkI⋅(n+1)..]"
apply (rule filter_cong[rule_format])
apply (rename_tac x, case_tac x)
using ‹n > 1›
apply auto
done
also have "... = filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d ≤ n ⟶ ¬ (d dvd i))))⋅[MkI⋅(int n+1)..]"
by (metis (no_types, lifting) of_nat_1 of_nat_add)
also have "... = filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d ≤ n ⟶ ¬ (d dvd i))))⋅[MkI⋅n'..]"
apply (rule filter_fast_forward[of n n']) using ‹n' > n›
apply (auto simp add: between_have_divisors)
done
also have "... = filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < n' ⟶ ¬ (d dvd i))))⋅[MkI⋅n'..]"
by (auto intro: filter_cong[rule_format] simp add: between_not_relvant)
also note calculation
}
note tmp = this
{
have "xs = sieve⋅?xs" by fact
also have "... = sieve⋅((MkI⋅n) : xs')" using ‹?xs = _› by simp
also have "... = sieve⋅((MkI⋅n) : filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < n ⟶ ¬ (d dvd i))))⋅[MkI⋅(n+1)..])" using ‹xs' = _› by simp
also have "... = (MkI⋅n) : sieve⋅(filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < n' ⟶ ¬ (d dvd i))))⋅[MkI⋅n'..])" using tmp by simp
also note calculation
}
moreover
{
have "ys = filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅n..]" by fact
also have "... = (MkI⋅n) : filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅(int n+1)..]"
using ‹prime n›
by (subst intsFrom.simps[unfolded enumFrom_intsFrom_conv[symmetric]])(simp add: one_Integer_def TT_def[symmetric] add.commute)
also have "... = (MkI⋅n) : filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅n'..]"
apply (subst filter_fast_forward[of n n']) using ‹n' > n› and not_prime
apply auto
apply (metis (full_types) ‹⋀k. ⟦int n < k; k < int n'⟧ ⟹ ∃d>1. d ≤ int n ∧ d dvd k› le_less not_le prime_gt_0_int prime_int_not_dvd zdvd_imp_le)
done
also note calculation
}
moreover
note ‹prime n'›
ultimately
have "∃ p xs' ys'. xs = p : xs' ∧ ys = p : ys' ∧ prim_bisim xs' ys'" unfolding prim_bisim
using prime_nat_int_transfer by blast
}
then show ?thesis unfolding list.bisim_def by metis
qed
text ‹Now we apply coinduction:›
lemma sieve_produces_primes:
fixes n :: nat
assumes "prime n"
shows "sieve⋅(filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < n ⟶ ¬ (d dvd i))))⋅[MkI⋅n..])
= filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅n..]"
using assms
apply -
apply (rule list.coinduct[OF prim_bisim_is_bisim], auto simp add: prim_bisim)
using prime_nat_int_transfer by blast
text ‹And finally show the correctness of primes.›
theorem primes:
shows "primes = filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅2..]"
proof -
have "primes = sieve⋅[2 ..]" by (rule primes.simps)
also have "... = sieve⋅(filter⋅(Λ (MkI⋅i). Def ((∀d::int. d > 1 ⟶ d < (int 2) ⟶ ¬ (d dvd i))))⋅[MkI⋅(int 2)..])"
unfolding numeral_Integer_eq
by (subst filter_TT, auto)
also have "... = filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅(int 2)..]"
by (rule sieve_produces_primes[OF two_is_prime_nat])
also have "... = filter⋅(Λ (MkI⋅i). Def (prime (nat ¦i¦)))⋅[MkI⋅2..]"
by simp
finally show ?thesis .
qed
end
Theory GHC_Rewrite_Rules
section ‹GHC's "fold/build" Rule›
theory GHC_Rewrite_Rules
imports "../HOLCF_Prelude"
begin
subsection ‹Approximating the Rewrite Rule›
text ‹
The original rule looks as follows (see also \cite{ghc-rewriting}):
\begin{verbatim}
"fold/build"
forall k z (g :: forall b. (a -> b -> b) -> b -> b).
foldr k z (build g) = g k z
\end{verbatim}
Since we do not have rank-2 polymorphic types in Isabelle/HOL, we try to imitate a similar
statement by introducing a new type that combines possible folds with their argument lists, i.e.,
@{term f} below is a function that, in a way, represents the list @{term xs}, but where list
constructors are functionally abstracted.
›
abbreviation (input) abstract_list where
"abstract_list xs ≡ (Λ c n. foldr⋅c⋅n⋅xs)"
cpodef ('a, 'b) listfun =
"{(f :: ('a → 'b → 'b) → 'b → 'b, xs). f = abstract_list xs}"
by auto
definition listfun :: "('a, 'b) listfun → ('a → 'b → 'b) → 'b → 'b" where
"listfun = (Λ g. Product_Type.fst (Rep_listfun g))"
definition build :: "('a, 'b) listfun → ['a]" where
"build = (Λ g. Product_Type.snd (Rep_listfun g))"
definition augment :: "('a, 'b) listfun → ['a] → ['a]" where
"augment = (Λ g xs. build⋅g ++ xs)"
definition listfun_comp :: "('a, 'b) listfun → ('a, 'b) listfun → ('a, 'b) listfun" where
"listfun_comp = (Λ g h.
Abs_listfun (Λ c n. listfun⋅g⋅c⋅(listfun⋅h⋅c⋅n), build⋅g ++ build⋅h))"
abbreviation
listfun_comp_infix :: "('a, 'b) listfun ⇒ ('a, 'b) listfun ⇒ ('a, 'b) listfun" (infixl "∘lf" 55)
where
"g ∘lf h ≡ listfun_comp⋅g⋅h"
fixrec mapFB :: "('b → 'c → 'c) → ('a → 'b) → 'a → 'c → 'c" where
"mapFB⋅c⋅f = (Λ x ys. c⋅(f⋅x)⋅ys)"
subsection ‹Lemmas›
lemma cont_listfun_body [simp]:
"cont (λg. Product_Type.fst (Rep_listfun g))"
by (simp add: cont_Rep_listfun)
lemma cont_build_body [simp]:
"cont (λg. Product_Type.snd (Rep_listfun g))"
by (simp add: cont_Rep_listfun)
lemma build_Abs_listfun:
assumes "abstract_list xs = f"
shows "build⋅(Abs_listfun (f, xs)) = xs"
using assms and Abs_listfun_inverse [of "(f, xs)"]
by (simp add: build_def)
lemma listfun_Abs_listfun [simp]:
assumes "abstract_list xs = f"
shows "listfun⋅(Abs_listfun (f, xs)) = f"
using assms and Abs_listfun_inverse [of "(f, xs)"]
by (simp add: listfun_def)
lemma augment_Abs_listfun [simp]:
assumes "abstract_list xs = f"
shows "augment⋅(Abs_listfun (f, xs))⋅ys = xs ++ ys"
using assms and Abs_listfun_inverse [of "(f, xs)"]
by (simp add: augment_def build_Abs_listfun)
lemma cont_augment_body [simp]:
"cont (λg. Abs_cfun ((++) (Product_Type.snd (Rep_listfun g))))"
by (simp add: cont_Rep_listfun)
lemma "fold/build":
fixes g :: "('a, 'b) listfun"
shows "foldr⋅k⋅z⋅(build⋅g) = listfun⋅g⋅k⋅z"
proof -
from Rep_listfun obtain f xs where
"Rep_listfun g = (f, xs)" and "f = abstract_list xs" by blast
then show ?thesis by (simp add: build_def listfun_def)
qed
lemma "foldr/augment":
fixes g :: "('a, 'b) listfun"
shows "foldr⋅k⋅z⋅(augment⋅g⋅xs) = listfun⋅g⋅k⋅(foldr⋅k⋅z⋅xs)"
proof -
from Rep_listfun obtain f ys where
"Rep_listfun g = (f, ys)" and "f = abstract_list ys" by blast
then show ?thesis
by (simp add: augment_def build_def listfun_def)
qed
lemma "foldr/id":
"foldr⋅(:)⋅[] = (Λ x. x)"
proof (rule cfun_eqI)
fix xs :: "['a]"
show "foldr⋅(:)⋅[]⋅xs = (Λ x. x)⋅xs"
by (induction xs) simp+
qed
lemma "foldr/app":
"foldr⋅(:)⋅ys = (Λ xs. xs ++ ys)"
proof (rule cfun_eqI)
fix xs :: "['a]"
show "foldr⋅(:)⋅ys⋅xs = (Λ xs. xs ++ ys)⋅xs" by (induct xs) simp+
qed
lemma "foldr/cons": "foldr⋅k⋅z⋅(x:xs) = k⋅x⋅(foldr⋅k⋅z⋅xs)" by simp
lemma "foldr/single": "foldr⋅k⋅z⋅[x] = k⋅x⋅z" by simp
lemma "foldr/nil": "foldr⋅k⋅z⋅[] = z" by simp
lemma cont_listfun_comp_body1 [simp]:
"cont (λh. Abs_listfun (Λ c n. listfun⋅g⋅c⋅(listfun⋅h⋅c⋅n), build⋅g ++ build⋅h))"
proof -
have "⋀h.
(Λ c n. listfun⋅g⋅c⋅(listfun⋅h⋅c⋅n), build⋅g ++ build⋅h) ∈ {(f, xs). f = abstract_list xs}"
by (simp add: "fold/build")
from cont_Abs_listfun [OF this, of "λx. x"]
show ?thesis by simp
qed
lemma cont_listfun_comp_body2 [simp]:
"cont (λg. Abs_listfun (Λ c n. listfun⋅g⋅c⋅(listfun⋅h⋅c⋅n), build⋅g ++ build⋅h))"
proof -
have "⋀g.
(Λ c n. listfun⋅g⋅c⋅(listfun⋅h⋅c⋅n), build⋅g ++ build⋅h) ∈ {(f, xs). f = abstract_list xs}"
by (simp add: "fold/build")
from cont_Abs_listfun [OF this, of "λx. x"]
show ?thesis by simp
qed
lemma cont_listfun_comp_body [simp]:
"cont (λg. Λ h. Abs_listfun (Λ c n. listfun⋅g⋅c⋅(listfun⋅h⋅c⋅n), build⋅g ++ build⋅h))"
by (rule cont2cont_LAM) simp+
lemma abstract_list_build_append:
"abstract_list (build⋅g ++ build⋅h) = (Λ c n. listfun⋅g⋅c⋅(listfun⋅h⋅c⋅n))"
by (intro cfun_eqI) (simp add: "fold/build")
lemma "augment/build":
"augment⋅g⋅(build⋅h) = build⋅(g ∘lf h)"
by (simp add: listfun_comp_def augment_def build_Abs_listfun [OF abstract_list_build_append])
lemma "augment/nil":
"augment⋅g⋅[] = build⋅g"
by (simp add: augment_def)
lemma build_listfun_comp [simp]:
"build⋅(g ∘lf h) = build⋅g ++ build⋅h"
unfolding "augment/build" [symmetric]
by (simp add: augment_def)
lemma augment_augment:
"augment⋅g⋅(augment⋅h⋅xs) = augment⋅(g ∘lf h)⋅xs"
by (simp add: augment_def)
lemma abstract_list_map [simp]:
"abstract_list (map⋅f⋅xs) = (Λ c n. foldr⋅(mapFB⋅c⋅f)⋅n⋅xs)"
by (intro cfun_eqI, induct xs) simp+
lemma "map":
"map⋅f⋅xs = build⋅(Abs_listfun (Λ c n. foldr⋅(mapFB⋅c⋅f)⋅n⋅xs, map⋅f⋅xs))"
by (simp add: build_Abs_listfun)
lemma "mapList":
"foldr⋅(mapFB⋅(:)