Theory List_Filtermap
section ‹Filtermap for Lazy Lists›
theory List_Filtermap
imports Main
begin
text ‹ This theory defines the filtermap operator for lazy lists, proves its basic properties,
and proves coinductive criteria for the equqlity of two filtermapped lazy lsits. ›
subsection ‹ Preliminaries ›
hide_const filtermap
abbreviation never :: "('a ⇒ bool) ⇒ 'a list ⇒ bool" where "never U ≡ list_all (λ a. ¬ U a)"
lemma never_list_ex: "never pred xs ⟷ ¬ list_ex pred xs"
by (induction xs) auto
abbreviation Rcons (infix "##" 70) where "xs ## x ≡ xs @ [x]"
lemma two_singl_Rcons: "[a,b] = [a] ## b" by auto
lemma length_gt_1_Cons_snoc:
assumes "length ys > 1"
obtains x1 xs x2 where "ys = x1 # xs ## x2"
using assms
proof (cases ys)
case (Cons x1 xs)
with assms obtain xs' x2 where "xs = xs' ## x2" by (cases xs rule: rev_cases) auto
with Cons show thesis by (intro that) auto
qed auto
lemma right_cons_left[simp]: "i < length as ⟹ (as ## a)!i = as!i"
by (metis butlast_snoc nth_butlast)+
subsection ‹ Filtermap ›
definition filtermap :: "('b ⇒ bool) ⇒ ('b ⇒ 'a) ⇒ 'b list ⇒ 'a list" where
"filtermap pred func xs ≡ map func (filter pred xs)"
lemma filtermap_Nil[simp]:
"filtermap pred func [] = []"
unfolding filtermap_def by auto
lemma filtermap_Cons_not[simp]:
"¬ pred x ⟹ filtermap pred func (x # xs) = filtermap pred func xs"
unfolding filtermap_def by auto
lemma filtermap_Cons[simp]:
"pred x ⟹ filtermap pred func (x # xs) = func x # filtermap pred func xs"
unfolding filtermap_def by auto
lemma filtermap_append: "filtermap pred func (xs @ xs1) = filtermap pred func xs @ filtermap pred func xs1"
proof(induction xs arbitrary: xs1)
case (Cons x xs)
thus ?case by (cases "pred x") auto
qed auto
lemma filtermap_Nil_list_ex: "filtermap pred func xs = [] ⟷ ¬ list_ex pred xs"
proof(induction xs)
case (Cons x xs)
thus ?case by (cases "pred x") auto
qed auto
lemma filtermap_Nil_never: "filtermap pred func xs = [] ⟷ never pred xs"
proof(induction xs)
case (Cons x xs)
thus ?case by (cases "pred x") auto
qed auto
lemma length_filtermap: "length (filtermap pred func xs) ≤ length xs"
proof(induction xs)
case (Cons x xs)
thus ?case by (cases "pred x") auto
qed auto
lemma filtermap_list_all[simp]: "filtermap pred func xs = map func xs ⟷ list_all pred xs"
proof(induction xs)
case (Cons x xs)
thus ?case apply (cases "pred x")
by (simp_all) (metis impossible_Cons length_filtermap length_map)
qed auto
lemma filtermap_eq_Cons:
assumes "filtermap pred func xs = a # al1"
shows "∃ x xs2 xs1.
xs = xs2 @ [x] @ xs1 ∧ never pred xs2 ∧ pred x ∧ func x = a ∧ filtermap pred func xs1 = al1"
using assms proof(induction xs arbitrary: a al1)
case (Cons x xs a al1)
show ?case
proof(cases "pred x")
case False
hence "filtermap pred func xs = a # al1" using Cons by simp
from Cons(1)[OF this] obtain xn xs2 xs1 where
1: "xs = xs2 @ [xn] @ xs1 ∧ never pred xs2 ∧ pred xn ∧ func xn = a ∧
filtermap pred func xs1 = al1" by blast
show ?thesis apply(rule exI[of _ xn], rule exI[of _ "x # xs2"], rule exI[of _ xs1])
using Cons(2) 1 False by simp
next
case True
hence "filtermap pred func xs = al1" using Cons by simp
show ?thesis apply(rule exI[of _ x], rule exI[of _ "[]"], rule exI[of _ xs])
using Cons(2) True by simp
qed
qed auto
lemma filtermap_eq_append:
assumes "filtermap pred func xs = al1 @ al2"
shows "∃ xs1 xs2. xs = xs1 @ xs2 ∧ filtermap pred func xs1 = al1 ∧ filtermap pred func xs2 = al2"
using assms proof(induction al1 arbitrary: xs)
case Nil show ?case
apply (rule exI[of _ "[]"], rule exI[of _ xs]) using Nil by auto
next
case (Cons a al1 xs)
hence "filtermap pred func xs = a # (al1 @ al2)" by simp
from filtermap_eq_Cons[OF this] obtain x xs2 xs1
where xs: "xs = xs2 @ [x] @ xs1" and n: "never pred xs2 ∧ pred x ∧ func x = a"
and f: "filtermap pred func xs1 = al1 @ al2" by blast
from Cons(1)[OF f] obtain xs11 xs22 where xs1: "xs1 = xs11 @ xs22"
and f1: "filtermap pred func xs11 = al1" and f2: "filtermap pred func xs22 = al2" by blast
show ?case apply (rule exI[of _ "xs2 @ [x] @ xs11"], rule exI[of _ xs22])
using n filtermap_Nil_never f1 f2 unfolding xs xs1 filtermap_append by auto
qed
lemma holds_filtermap_RCons[simp]:
"pred x ⟹ filtermap pred func (xs ## x) = filtermap pred func xs ## func x"
proof(induction xs)
case (Cons x xs)
thus ?case by (cases "pred x") auto
qed auto
lemma not_holds_filtermap_RCons[simp]:
"¬ pred x ⟹ filtermap pred func (xs ## x) = filtermap pred func xs"
proof(induction xs)
case (Cons x xs)
thus ?case by (cases "pred x") auto
qed auto
lemma filtermap_eq_RCons:
assumes "filtermap pred func xs = al1 ## a"
shows "∃ x xs1 xs2.
xs = xs1 @ [x] @ xs2 ∧ never pred xs2 ∧ pred x ∧ func x = a ∧ filtermap pred func xs1 = al1"
using assms proof(induction xs arbitrary: a al1 rule: rev_induct)
case (snoc x xs a al1)
show ?case
proof(cases "pred x")
case False
hence "filtermap pred func xs = al1 ## a" using snoc by simp
from snoc(1)[OF this] obtain xn xs2 xs1 where
1: "xs = xs1 @ [xn] @ xs2 ∧ never pred xs2 ∧ pred xn ∧ func xn = a ∧
filtermap pred func xs1 = al1" by blast
show ?thesis apply(rule exI[of _ xn], rule exI[of _ xs1], rule exI[of _ "xs2 ## x"])
using snoc(2) 1 False by simp
next
case True
hence "filtermap pred func xs = al1" using snoc by simp
show ?thesis apply(rule exI[of _ x], rule exI[of _ xs], rule exI[of _ "[]"])
using snoc(2) True by simp
qed
qed auto
lemma filtermap_eq_Cons_RCons:
assumes "filtermap pred func xs = a # al1 ## b"
shows "∃ xsa xa xs1 xb xsb.
xs = xsa @ [xa] @ xs1 @ [xb] @ xsb ∧
never pred xsa ∧
pred xa ∧ func xa = a ∧
filtermap pred func xs1 = al1 ∧
pred xb ∧ func xb = b ∧
never pred xsb"
proof-
from filtermap_eq_Cons[OF assms] obtain xa xsa xs2
where 0: "xs = xsa @ [xa] @ xs2 ∧ never pred xsa ∧ pred xa ∧ func xa = a"
and 1: "filtermap pred func xs2 = al1 ## b" by auto
from filtermap_eq_RCons[OF 1] obtain xb xs1 xsb where
2: "xs2 = xs1 @ [xb] @ xsb ∧ never pred xsb ∧
pred xb ∧ func xb = b ∧ filtermap pred func xs1 = al1" by blast
show ?thesis apply(rule exI[of _ xsa], rule exI[of _ xa], rule exI[of _ xs1],
rule exI[of _ xb], rule exI[of _ xsb])
using 2 0 by auto
qed
lemma filter_Nil_never: "[] = filter pred xs ⟹ never pred xs"
by (induction xs) (auto split: if_splits)
lemma never_Nil_filter: "never pred xs ⟷ [] = filter pred xs"
by (induction xs) (auto split: if_splits)
lemma set_filtermap:
"set (filtermap pred func xs) ⊆ {func x | x . x ∈ set xs ∧ pred x}"
proof(induction xs)
case (Cons x xs)
thus ?case by (cases "pred x") auto
qed auto
end