Theory Ssum

Up to index of Isabelle/HOLCF

theory Ssum
imports Tr

(*  Title:      HOLCF/Ssum.thy
Author: Franz Regensburger and Brian Huffman
*)


header {* The type of strict sums *}

theory Ssum
imports Tr
begin


default_sort pcpo

subsection {* Definition of strict sum type *}

pcpodef (Ssum) ('a, 'b) ssum (infixr "++" 10) =
"{p :: tr × ('a × 'b).
(fst p \<sqsubseteq> TT <-> snd (snd p) = ⊥) ∧
(fst p \<sqsubseteq> FF <-> fst (snd p) = ⊥)}"

by simp_all

instance ssum :: ("{finite_po,pcpo}", "{finite_po,pcpo}") finite_po
by (rule typedef_finite_po [OF type_definition_Ssum])

instance ssum :: ("{chfin,pcpo}", "{chfin,pcpo}") chfin
by (rule typedef_chfin [OF type_definition_Ssum below_Ssum_def])

type_notation (xsymbols)
ssum ("(_ ⊕/ _)" [21, 20] 20)

type_notation (HTML output)
ssum ("(_ ⊕/ _)" [21, 20] 20)



subsection {* Definitions of constructors *}

definition
sinl :: "'a -> ('a ++ 'b)" where
"sinl = (Λ a. Abs_Ssum (strictify·(Λ _. TT)·a, a, ⊥))"


definition
sinr :: "'b -> ('a ++ 'b)" where
"sinr = (Λ b. Abs_Ssum (strictify·(Λ _. FF)·b, ⊥, b))"


lemma sinl_Ssum: "(strictify·(Λ _. TT)·a, a, ⊥) ∈ Ssum"
by (simp add: Ssum_def strictify_conv_if)

lemma sinr_Ssum: "(strictify·(Λ _. FF)·b, ⊥, b) ∈ Ssum"
by (simp add: Ssum_def strictify_conv_if)

lemma sinl_Abs_Ssum: "sinl·a = Abs_Ssum (strictify·(Λ _. TT)·a, a, ⊥)"
by (unfold sinl_def, simp add: cont_Abs_Ssum sinl_Ssum)

lemma sinr_Abs_Ssum: "sinr·b = Abs_Ssum (strictify·(Λ _. FF)·b, ⊥, b)"
by (unfold sinr_def, simp add: cont_Abs_Ssum sinr_Ssum)

lemma Rep_Ssum_sinl: "Rep_Ssum (sinl·a) = (strictify·(Λ _. TT)·a, a, ⊥)"
by (simp add: sinl_Abs_Ssum Abs_Ssum_inverse sinl_Ssum)

lemma Rep_Ssum_sinr: "Rep_Ssum (sinr·b) = (strictify·(Λ _. FF)·b, ⊥, b)"
by (simp add: sinr_Abs_Ssum Abs_Ssum_inverse sinr_Ssum)

subsection {* Properties of \emph{sinl} and \emph{sinr} *}

text {* Ordering *}

lemma sinl_below [simp]: "(sinl·x \<sqsubseteq> sinl·y) = (x \<sqsubseteq> y)"
by (simp add: below_Ssum_def Rep_Ssum_sinl strictify_conv_if)

lemma sinr_below [simp]: "(sinr·x \<sqsubseteq> sinr·y) = (x \<sqsubseteq> y)"
by (simp add: below_Ssum_def Rep_Ssum_sinr strictify_conv_if)

lemma sinl_below_sinr [simp]: "(sinl·x \<sqsubseteq> sinr·y) = (x = ⊥)"
by (simp add: below_Ssum_def Rep_Ssum_sinl Rep_Ssum_sinr strictify_conv_if)

lemma sinr_below_sinl [simp]: "(sinr·x \<sqsubseteq> sinl·y) = (x = ⊥)"
by (simp add: below_Ssum_def Rep_Ssum_sinl Rep_Ssum_sinr strictify_conv_if)

text {* Equality *}

lemma sinl_eq [simp]: "(sinl·x = sinl·y) = (x = y)"
by (simp add: po_eq_conv)

lemma sinr_eq [simp]: "(sinr·x = sinr·y) = (x = y)"
by (simp add: po_eq_conv)

lemma sinl_eq_sinr [simp]: "(sinl·x = sinr·y) = (x = ⊥ ∧ y = ⊥)"
by (subst po_eq_conv, simp)

lemma sinr_eq_sinl [simp]: "(sinr·x = sinl·y) = (x = ⊥ ∧ y = ⊥)"
by (subst po_eq_conv, simp)

lemma sinl_inject: "sinl·x = sinl·y ==> x = y"
by (rule sinl_eq [THEN iffD1])

lemma sinr_inject: "sinr·x = sinr·y ==> x = y"
by (rule sinr_eq [THEN iffD1])

text {* Strictness *}

lemma sinl_strict [simp]: "sinl·⊥ = ⊥"
by (simp add: sinl_Abs_Ssum Abs_Ssum_strict)

lemma sinr_strict [simp]: "sinr·⊥ = ⊥"
by (simp add: sinr_Abs_Ssum Abs_Ssum_strict)

lemma sinl_defined_iff [simp]: "(sinl·x = ⊥) = (x = ⊥)"
by (cut_tac sinl_eq [of "x" "⊥"], simp)

lemma sinr_defined_iff [simp]: "(sinr·x = ⊥) = (x = ⊥)"
by (cut_tac sinr_eq [of "x" "⊥"], simp)

lemma sinl_defined [intro!]: "x ≠ ⊥ ==> sinl·x ≠ ⊥"
by simp

lemma sinr_defined [intro!]: "x ≠ ⊥ ==> sinr·x ≠ ⊥"
by simp

text {* Compactness *}

lemma compact_sinl: "compact x ==> compact (sinl·x)"
by (rule compact_Ssum, simp add: Rep_Ssum_sinl strictify_conv_if)

lemma compact_sinr: "compact x ==> compact (sinr·x)"
by (rule compact_Ssum, simp add: Rep_Ssum_sinr strictify_conv_if)

lemma compact_sinlD: "compact (sinl·x) ==> compact x"
unfolding compact_def
by (drule adm_subst [OF cont_Rep_CFun2 [where f=sinl]], simp)

lemma compact_sinrD: "compact (sinr·x) ==> compact x"
unfolding compact_def
by (drule adm_subst [OF cont_Rep_CFun2 [where f=sinr]], simp)

lemma compact_sinl_iff [simp]: "compact (sinl·x) = compact x"
by (safe elim!: compact_sinl compact_sinlD)

lemma compact_sinr_iff [simp]: "compact (sinr·x) = compact x"
by (safe elim!: compact_sinr compact_sinrD)

subsection {* Case analysis *}

lemma Exh_Ssum:
"z = ⊥ ∨ (∃a. z = sinl·a ∧ a ≠ ⊥) ∨ (∃b. z = sinr·b ∧ b ≠ ⊥)"

apply (induct z rule: Abs_Ssum_induct)
apply (case_tac y, rename_tac t a b)
apply (case_tac t rule: trE)
apply (rule disjI1)
apply (simp add: Ssum_def Abs_Ssum_strict)
apply (rule disjI2, rule disjI1, rule_tac x=a in exI)
apply (simp add: sinl_Abs_Ssum Ssum_def)
apply (rule disjI2, rule disjI2, rule_tac x=b in exI)
apply (simp add: sinr_Abs_Ssum Ssum_def)
done

lemma ssumE [case_names bottom sinl sinr, cases type: ssum]:
"[|p = ⊥ ==> Q;
!!x. [|p = sinl·x; x ≠ ⊥|] ==> Q;
!!y. [|p = sinr·y; y ≠ ⊥|] ==> Q|] ==> Q"

using Exh_Ssum [of p] by auto

lemma ssum_induct [case_names bottom sinl sinr, induct type: ssum]:
"[|P ⊥;
!!x. x ≠ ⊥ ==> P (sinl·x);
!!y. y ≠ ⊥ ==> P (sinr·y)|] ==> P x"

by (cases x, simp_all)

lemma ssumE2 [case_names sinl sinr]:
"[|!!x. p = sinl·x ==> Q; !!y. p = sinr·y ==> Q|] ==> Q"

by (cases p, simp only: sinl_strict [symmetric], simp, simp)

lemma below_sinlD: "p \<sqsubseteq> sinl·x ==> ∃y. p = sinl·y ∧ y \<sqsubseteq> x"
by (cases p, rule_tac x="⊥" in exI, simp_all)

lemma below_sinrD: "p \<sqsubseteq> sinr·x ==> ∃y. p = sinr·y ∧ y \<sqsubseteq> x"
by (cases p, rule_tac x="⊥" in exI, simp_all)

subsection {* Case analysis combinator *}

definition
sscase :: "('a -> 'c) -> ('b -> 'c) -> ('a ++ 'b) -> 'c" where
"sscase = (Λ f g s. (λ(t, x, y). If t then f·x else g·y fi) (Rep_Ssum s))"


translations
"case s of XCONST sinl·x => t1 | XCONST sinr·y => t2" == "CONST sscase·(Λ x. t1)·(Λ y. t2)·s"


translations
"Λ(XCONST sinl·x). t" == "CONST sscase·(Λ x. t)·⊥"
"Λ(XCONST sinr·y). t" == "CONST sscase·⊥·(Λ y. t)"


lemma beta_sscase:
"sscase·f·g·s = (λ(t, x, y). If t then f·x else g·y fi) (Rep_Ssum s)"

unfolding sscase_def by (simp add: cont_Rep_Ssum [THEN cont_compose])

lemma sscase1 [simp]: "sscase·f·g·⊥ = ⊥"
unfolding beta_sscase by (simp add: Rep_Ssum_strict)

lemma sscase2 [simp]: "x ≠ ⊥ ==> sscase·f·g·(sinl·x) = f·x"
unfolding beta_sscase by (simp add: Rep_Ssum_sinl)

lemma sscase3 [simp]: "y ≠ ⊥ ==> sscase·f·g·(sinr·y) = g·y"
unfolding beta_sscase by (simp add: Rep_Ssum_sinr)

lemma sscase4 [simp]: "sscase·sinl·sinr·z = z"
by (cases z, simp_all)

subsection {* Strict sum preserves flatness *}

instance ssum :: (flat, flat) flat
apply (intro_classes, clarify)
apply (case_tac x, simp)
apply (case_tac y, simp_all add: flat_below_iff)
apply (case_tac y, simp_all add: flat_below_iff)
done

subsection {* Map function for strict sums *}

definition
ssum_map :: "('a -> 'b) -> ('c -> 'd) -> 'a ⊕ 'c -> 'b ⊕ 'd"
where
"ssum_map = (Λ f g. sscase·(sinl oo f)·(sinr oo g))"


lemma ssum_map_strict [simp]: "ssum_map·f·g·⊥ = ⊥"
unfolding ssum_map_def by simp

lemma ssum_map_sinl [simp]: "x ≠ ⊥ ==> ssum_map·f·g·(sinl·x) = sinl·(f·x)"
unfolding ssum_map_def by simp

lemma ssum_map_sinr [simp]: "x ≠ ⊥ ==> ssum_map·f·g·(sinr·x) = sinr·(g·x)"
unfolding ssum_map_def by simp

lemma ssum_map_sinl': "f·⊥ = ⊥ ==> ssum_map·f·g·(sinl·x) = sinl·(f·x)"
by (cases "x = ⊥") simp_all

lemma ssum_map_sinr': "g·⊥ = ⊥ ==> ssum_map·f·g·(sinr·x) = sinr·(g·x)"
by (cases "x = ⊥") simp_all

lemma ssum_map_ID: "ssum_map·ID·ID = ID"
unfolding ssum_map_def by (simp add: expand_cfun_eq eta_cfun)

lemma ssum_map_map:
"[|f1·⊥ = ⊥; g1·⊥ = ⊥|] ==>
ssum_map·f1·g1·(ssum_map·f2·g2·p) =
ssum_map·(Λ x. f1·(f2·x))·(Λ x. g1·(g2·x))·p"

apply (induct p, simp)
apply (case_tac "f2·x = ⊥", simp, simp)
apply (case_tac "g2·y = ⊥", simp, simp)
done

lemma ep_pair_ssum_map:
assumes "ep_pair e1 p1" and "ep_pair e2 p2"
shows "ep_pair (ssum_map·e1·e2) (ssum_map·p1·p2)"

proof
interpret e1p1: pcpo_ep_pair e1 p1 unfolding pcpo_ep_pair_def by fact
interpret e2p2: pcpo_ep_pair e2 p2 unfolding pcpo_ep_pair_def by fact
fix x show "ssum_map·p1·p2·(ssum_map·e1·e2·x) = x"
by (induct x) simp_all
fix y show "ssum_map·e1·e2·(ssum_map·p1·p2·y) \<sqsubseteq> y"
apply (induct y, simp)
apply (case_tac "p1·x = ⊥", simp, simp add: e1p1.e_p_below)
apply (case_tac "p2·y = ⊥", simp, simp add: e2p2.e_p_below)
done
qed

lemma deflation_ssum_map:
assumes "deflation d1" and "deflation d2"
shows "deflation (ssum_map·d1·d2)"

proof
interpret d1: deflation d1 by fact
interpret d2: deflation d2 by fact
fix x
show "ssum_map·d1·d2·(ssum_map·d1·d2·x) = ssum_map·d1·d2·x"
apply (induct x, simp)
apply (case_tac "d1·x = ⊥", simp, simp add: d1.idem)
apply (case_tac "d2·y = ⊥", simp, simp add: d2.idem)
done
show "ssum_map·d1·d2·x \<sqsubseteq> x"
apply (induct x, simp)
apply (case_tac "d1·x = ⊥", simp, simp add: d1.below)
apply (case_tac "d2·y = ⊥", simp, simp add: d2.below)
done
qed

lemma finite_deflation_ssum_map:
assumes "finite_deflation d1" and "finite_deflation d2"
shows "finite_deflation (ssum_map·d1·d2)"

proof (intro finite_deflation.intro finite_deflation_axioms.intro)
interpret d1: finite_deflation d1 by fact
interpret d2: finite_deflation d2 by fact
have "deflation d1" and "deflation d2" by fact+
thus "deflation (ssum_map·d1·d2)" by (rule deflation_ssum_map)
have "{x. ssum_map·d1·d2·x = x} ⊆
(λx. sinl·x) ` {x. d1·x = x} ∪
(λx. sinr·x) ` {x. d2·x = x} ∪ {⊥}"

by (rule subsetI, case_tac x, simp_all)
thus "finite {x. ssum_map·d1·d2·x = x}"
by (rule finite_subset, simp add: d1.finite_fixes d2.finite_fixes)
qed

subsection {* Strict sum is a bifinite domain *}

instantiation ssum :: (bifinite, bifinite) bifinite
begin


definition
approx_ssum_def:
"approx = (λn. ssum_map·(approx n)·(approx n))"


lemma approx_sinl [simp]: "approx i·(sinl·x) = sinl·(approx i·x)"
unfolding approx_ssum_def by (cases "x = ⊥") simp_all

lemma approx_sinr [simp]: "approx i·(sinr·x) = sinr·(approx i·x)"
unfolding approx_ssum_def by (cases "x = ⊥") simp_all

instance proof
fix i :: nat and x :: "'a ⊕ 'b"
show "chain (approx :: nat => 'a ⊕ 'b -> 'a ⊕ 'b)"
unfolding approx_ssum_def by simp
show "(\<Squnion>i. approx i·x) = x"
unfolding approx_ssum_def
by (cases x, simp_all add: lub_distribs)
show "approx i·(approx i·x) = approx i·x"
by (cases x, simp add: approx_ssum_def, simp, simp)
show "finite {x::'a ⊕ 'b. approx i·x = x}"
unfolding approx_ssum_def
by (intro finite_deflation.finite_fixes
finite_deflation_ssum_map
finite_deflation_approx)

qed

end

end