Theory Bounded_List
section ‹ Bounded Lists ›
theory Bounded_List
imports "List_Extra" "HOL-Library.Numeral_Type"
begin
text ‹ The term @{term "CARD('n)"} retrieves the cardinality of a finite type @{typ 'n}. Examples
include the types @{typ 1}, @{typ 2} and @{typ 3}.›
typedef ('a, 'n::finite) blist = "{xs :: 'a list. length xs ≤ CARD('n)}"
morphisms list_of_blist blist_of_list
proof
show "[] ∈ {xs. length xs ≤ CARD('n)}"
by simp
qed
declare list_of_blist_inverse [simp]
syntax "_blist" :: "type ⇒ type ⇒ type" ("_ blist[_]" [100, 0] 100)
translations (type) "'a blist['n]" == (type) "('a, 'n) blist"
text ‹ We construct various functions using the lifting package to lift corresponding list functions. ›
setup_lifting type_definition_blist
lift_definition blength :: "'a blist['n::finite] ⇒ nat" is length .
lift_definition bnth :: "'a blist['n::finite] ⇒ nat ⇒ 'a" is nth .
lift_definition bappend :: "'a blist['m::finite] ⇒ 'a blist['n::finite] ⇒ 'a blist['m + 'n]" (infixr "@⇩s" 65) is append
by auto
lift_definition bmake :: "'n itself ⇒ 'a list ⇒ 'a blist['n::finite]" is "λ _. take CARD('n)"
by auto
code_datatype bmake
lemma bmake_length_card:
"blength (bmake TYPE('n::finite) xs) = (if length xs ≤ CARD('n) then length xs else CARD('n))"
by (simp add: blength_def bmake_def, auto simp add: blist_of_list_inverse)
lemma blist_always_bounded:
"length (list_of_blist (bl::'a blist['n::finite])) ≤ CARD('n)"
using list_of_blist by blast
lemma blist_remove_head:
fixes bl :: "'a blist['n::finite]"
assumes "blength bl > 0"
shows "blength (bmake TYPE('n::finite) (tl (list_of_blist (bl::'a blist['n::finite])))) < blength bl"
by (metis One_nat_def Suc_pred assms blength.rep_eq bmake_length_card length_tl less_Suc_eq_le linear)
text ‹ This proof is performed by transfer ›
lemma bappend_bmake [code]:
"bmake TYPE('a::finite) xs @⇩s bmake TYPE('b::finite) ys
= bmake TYPE('a + 'b) (take CARD('a) xs @ take CARD('b) ys)"
by (transfer, simp)
instantiation blist :: (type, finite) equal
begin
definition equal_blist :: "'a blist['b] ⇒ 'a blist['b] ⇒ bool" where
"equal_blist m1 m2 ⟷ (list_of_blist m1 = list_of_blist m2)"
instance proof
fix x y :: "'a blist['b]"
show "equal_class.equal x y = (x = y)"
by (simp add: equal_blist_def, transfer, simp)
qed
end
lemma list_of_blist_code [code]:
"list_of_blist (bmake TYPE('n::finite) xs) = take CARD('n) xs"
by (transfer, simp)+
definition blists :: "'n::finite itself ⇒ 'a list ⇒ ('a blist['n]) list" where
"blists n xs = map blist_of_list (b_lists CARD('n) xs)"
lemma n_blists_as_b_lists:
fixes n::"'n::finite itself"
shows "map list_of_blist (blists n xs) = b_lists CARD('n) xs" (is "?lhs = ?rhs")
proof -
have "?lhs = map (list_of_blist ∘ (blist_of_list :: _ ⇒ _ blist['n])) (b_lists CARD('n) xs)"
by (simp add: blists_def)
also have "... = map id (b_lists CARD('n) xs)"
by (rule map_cong, auto simp add: blist_of_list_inverse length_b_lists_elem)
also have "... = b_lists CARD('n) xs"
by simp
finally show ?thesis .
qed
lemma set_blists_enum_UNIV: "set (blists TYPE('n::finite) (enum_class.enum ::'a::enum list)) = UNIV"
proof -
have "⋀x:: 'a blist['n]. list_of_blist x ∈ set (b_lists CARD('n) enum_class.enum)"
proof (rule in_blistsI)
fix x::"'a blist['n]"
show "length (list_of_blist x) ≤ CARD('n)"
by (simp add: blist_always_bounded)
show "list_of_blist x ∈ lists (set enum_class.enum)"
by (auto simp add: lists_eq_set enum_UNIV)
qed
thus ?thesis
by (force simp add: blists_def image_iff)
qed
lemma distinct_blists: "distinct xs ⟹ distinct (blists n xs)"
by (metis distinct_b_lists distinct_map n_blists_as_b_lists)
definition all_blists :: "(('a::enum) blist['n::finite] ⇒ bool) ⇒ bool"
where
"all_blists P ⟷ (∀xs ∈ set (blists TYPE('n) Enum.enum). P xs)"
definition ex_blists :: "(('a :: enum) blist['n::finite] ⇒ bool) ⇒ bool"
where
"ex_blists P ⟷ (∃xs ∈ set (blists TYPE('n) Enum.enum). P xs)"
instantiation blist :: (enum, finite) enum
begin
definition enum_blist :: "('a blist['b]) list" where
"enum_blist = blists TYPE('b) Enum.enum"
definition enum_all_blist :: "('a blist['b] ⇒ bool) ⇒ bool" where
"enum_all_blist P = all_blists P"
definition enum_ex_blist :: "('a blist['b] ⇒ bool) ⇒ bool" where
"enum_ex_blist P = ex_blists P"
instance
by (intro_classes)
(simp_all add: enum_blist_def set_blists_enum_UNIV distinct_blists enum_distinct enum_all_blist_def enum_ex_blist_def all_blists_def ex_blists_def)
end
end