Theory Ssum

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

section ‹The type of strict sums›

theory Ssum
  imports Tr
begin

subsection ‹Definition of strict sum type›

definition "ssum =
  {p :: tr × ('a::pcpo × 'b::pcpo). p =  
    (fst p = TT  fst (snd p)    snd (snd p) = ) 
    (fst p = FF  fst (snd p) =   snd (snd p)  )}"

pcpodef ('a::pcpo, 'b::pcpo) ssum  ((‹notation=‹infix strict sum››_ / _) [21, 20] 20) =
  "ssum :: (tr × 'a × 'b) set"
  by (simp_all add: ssum_def)

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

type_notation (ASCII)
  ssum  (infixr ++ 10)


subsection ‹Definitions of constructors›

definition sinl :: "'a::pcpo  ('a ++ 'b::pcpo)"
  where "sinl = (Λ a. Abs_ssum (seqaTT, a, ))"

definition sinr :: "'b::pcpo  ('a::pcpo ++ 'b)"
  where "sinr = (Λ b. Abs_ssum (seqbFF, , b))"

lemma sinl_ssum: "(seqaTT, a, )  ssum"
  by (simp add: ssum_def seq_conv_if)

lemma sinr_ssum: "(seqbFF, , b)  ssum"
  by (simp add: ssum_def seq_conv_if)

lemma Rep_ssum_sinl: "Rep_ssum (sinla) = (seqaTT, a, )"
  by (simp add: sinl_def cont_Abs_ssum Abs_ssum_inverse sinl_ssum)

lemma Rep_ssum_sinr: "Rep_ssum (sinrb) = (seqbFF, , b)"
  by (simp add: sinr_def cont_Abs_ssum Abs_ssum_inverse sinr_ssum)

lemmas Rep_ssum_simps =
  Rep_ssum_inject [symmetric] below_ssum_def
  prod_eq_iff below_prod_def
  Rep_ssum_strict Rep_ssum_sinl Rep_ssum_sinr


subsection ‹Properties of \emph{sinl} and \emph{sinr}›

text ‹Ordering›

lemma sinl_below [simp]: "sinlx  sinly  x  y"
  by (simp add: Rep_ssum_simps seq_conv_if)

lemma sinr_below [simp]: "sinrx  sinry  x  y"
  by (simp add: Rep_ssum_simps seq_conv_if)

lemma sinl_below_sinr [simp]: "sinlx  sinry  x = "
  by (simp add: Rep_ssum_simps seq_conv_if)

lemma sinr_below_sinl [simp]: "sinrx  sinly  x = "
  by (simp add: Rep_ssum_simps seq_conv_if)

text ‹Equality›

lemma sinl_eq [simp]: "sinlx = sinly  x = y"
  by (simp add: po_eq_conv)

lemma sinr_eq [simp]: "sinrx = sinry  x = y"
  by (simp add: po_eq_conv)

lemma sinl_eq_sinr [simp]: "sinlx = sinry  x =   y = "
  by (subst po_eq_conv) simp

lemma sinr_eq_sinl [simp]: "sinrx = sinly  x =   y = "
  by (subst po_eq_conv) simp

lemma sinl_inject: "sinlx = sinly  x = y"
  by (rule sinl_eq [THEN iffD1])

lemma sinr_inject: "sinrx = sinry  x = y"
  by (rule sinr_eq [THEN iffD1])

text ‹Strictness›

lemma sinl_strict [simp]: "sinl = "
  by (simp add: Rep_ssum_simps)

lemma sinr_strict [simp]: "sinr = "
  by (simp add: Rep_ssum_simps)

lemma sinl_bottom_iff [simp]: "sinlx =   x = "
  using sinl_eq [of "x" ""] by simp

lemma sinr_bottom_iff [simp]: "sinrx =   x = "
  using sinr_eq [of "x" ""] by simp

lemma sinl_defined: "x    sinlx  "
  by simp

lemma sinr_defined: "x    sinrx  "
  by simp

text ‹Compactness›

lemma compact_sinl: "compact x  compact (sinlx)"
  by (rule compact_ssum) (simp add: Rep_ssum_sinl)

lemma compact_sinr: "compact x  compact (sinrx)"
  by (rule compact_ssum) (simp add: Rep_ssum_sinr)

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

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

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

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


subsection ‹Case analysis›

lemma ssumE [case_names bottom sinl sinr, cases type: ssum]:
  obtains "p = "
  | x where "p = sinlx" and "x  "
  | y where "p = sinry" and "y  "
  using Rep_ssum [of p] by (auto simp add: ssum_def Rep_ssum_simps)

lemma ssum_induct [case_names bottom sinl sinr, induct type: ssum]:
  "P ;
   x. x    P (sinlx);
   y. y    P (sinry)  P x"
  by (cases x) simp_all

lemma ssumE2 [case_names sinl sinr]:
  "x. p = sinlx  Q; y. p = sinry  Q  Q"
  by (cases p, simp only: sinl_strict [symmetric], simp, simp)

lemma below_sinlD: "p  sinlx  y. p = sinly  y  x"
  by (cases p, rule_tac x="" in exI, simp_all)

lemma below_sinrD: "p  sinrx  y. p = sinry  y  x"
  by (cases p, rule_tac x="" in exI, simp_all)


subsection ‹Case analysis combinator›

definition sscase :: "('a::pcpo  'c::pcpo)  ('b::pcpo  'c)  ('a ++ 'b)  'c"
  where "sscase = (Λ f g s. (λ(t, x, y). If t then fx else gy) (Rep_ssum s))"

translations
  "case s of XCONST sinlx  t1 | XCONST sinry  t2"  "CONST sscase(Λ x. t1)(Λ y. t2)s"
  "case s of (XCONST sinl :: 'a)x  t1 | XCONST sinry  t2"  "CONST sscase(Λ x. t1)(Λ y. t2)s"

translations
  "Λ(XCONST sinlx). t"  "CONST sscase(Λ x. t)"
  "Λ(XCONST sinry). t"  "CONST sscase(Λ y. t)"

lemma beta_sscase: "sscasefgs = (λ(t, x, y). If t then fx else gy) (Rep_ssum s)"
  by (simp add: sscase_def cont_Rep_ssum)

lemma sscase1 [simp]: "sscasefg = "
  by (simp add: beta_sscase Rep_ssum_strict)

lemma sscase2 [simp]: "x    sscasefg(sinlx) = fx"
  by (simp add: beta_sscase Rep_ssum_sinl)

lemma sscase3 [simp]: "y    sscasefg(sinry) = gy"
  by (simp add: beta_sscase Rep_ssum_sinr)

lemma sscase4 [simp]: "sscasesinlsinrz = 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

end