Theory Exceptions

(*<*)
theory Exceptions
imports
  "ConcurrentHOL.ConcurrentHOL"
begin

(*>*)
section‹ Exceptions\label{sec:exceptions} ›

text‹

A sketch of how we might handle exceptions in this framework.

›

setup Sign.mandatory_path "raw"

type_synonym ('s, 'x, 'v) exn = "('s, 'x + 'v) prog"

definition action :: "('v × 's × 's) set  ('s, 'x, 'v) raw.exn" where
  "action = prog.action  image (map_prod Inr id)"

definition return :: "'v  ('s, 'x, 'v) raw.exn" where
  "return = prog.return  Inr"

definition throw :: "'x  ('s, 'x, 'v) raw.exn" where
  "throw = prog.return  Inl"

definition catch :: "('s, 'x, 'v) raw.exn  ('x  ('s, 'x, 'v) raw.exn)  ('s, 'x, 'v) raw.exn" where
  "catch f handler = f  case_sum handler raw.return"

definition bind :: "('s, 'x, 'v) raw.exn  ('v  ('s, 'x, 'v) raw.exn)  ('s, 'x, 'v) raw.exn" where
  "bind f g = f  case_sum raw.throw g"

definition parallel :: "('s, 'x, unit) raw.exn  ('s, 'x, unit) raw.exn  ('s, 'x, unit) raw.exn" where
  "parallel P Q = (P  case_sum  prog.return  Q  case_sum  prog.return)  raw.return"

setup Sign.mandatory_path "bind"

lemma bind:
  shows "raw.bind (raw.bind f g) h = raw.bind f (λx. raw.bind (g x) h)"
by (simp add: raw.bind_def prog.bind.bind sum.case_distrib[where h="λf. f  case_sum raw.throw h"])
   (simp add: raw.throw_def comp_def prog.bind.return cong: sum.case_cong)

lemma return:
  shows returnL: "raw.bind (raw.return v) = (λg. g v)"
    and returnR: "raw.bind f raw.return = f"
by (simp_all add: fun_eq_iff raw.bind_def raw.return_def raw.throw_def prog.bind.return case_sum_Inl_Inr_L)

lemma throwL:
  shows "raw.bind (raw.throw x) = (λg. raw.throw x)"
by (simp add: fun_eq_iff raw.bind_def raw.throw_def prog.bind.return)

setup Sign.parent_path

setup Sign.mandatory_path "catch"

lemma catch:
  shows "raw.catch (raw.catch f handler1) handler2 = raw.catch f (λx. raw.catch (handler1 x) handler2)"
by (simp add: raw.catch_def prog.bind.bind sum.case_distrib[where h="λf. f  case_sum handler2 raw.return"])
   (simp add: raw.return_def comp_def prog.bind.return cong: sum.case_cong)

lemma returnL:
  shows "raw.catch (raw.return v) = (λhandler. raw.return v)"
by (simp add: fun_eq_iff raw.catch_def raw.return_def prog.bind.return)

lemma throw:
  shows throwL: "raw.catch (raw.throw x) = (λg. g x)"
    and throwR: "raw.catch f raw.throw = f"
by (simp_all add: fun_eq_iff raw.catch_def raw.return_def raw.throw_def prog.bind.return case_sum_Inl_Inr_L)

setup Sign.parent_path

setup Sign.mandatory_path "parallel"

lemma commute:
  shows "raw.parallel P Q = raw.parallel Q P"
by (simp add: raw.parallel_def prog.parallel.commute)

lemma assoc:
  shows "raw.parallel P (raw.parallel Q R) = raw.parallel (raw.parallel P Q) R"
by (simp add: raw.parallel_def raw.return_def prog.bind.bind prog.bind.return prog.parallel.assoc)

lemma return:
  shows "raw.parallel (raw.return ()) P = raw.catch P (λx. )" (is ?thesis1)
    and "raw.parallel P (raw.return ()) = raw.catch P (λx. )" (is ?thesis2)
proof -
  show ?thesis1
    by (simp add: raw.parallel_def raw.return_def
                  prog.bind.bind prog.bind.return prog.parallel.return prog.bind.botL
                  sum.case_distrib[where h="λf. f  prog.return  Inr"]
            flip: raw.catch_def[unfolded raw.return_def o_def]
            cong: sum.case_cong)
  then show ?thesis2
    by (simp add: raw.parallel.commute)
qed

lemma throw:
  shows "raw.parallel (raw.throw x) P = raw.bind (raw.catch P (λx. )) (λx. )" (is ?thesis1)
    and "raw.parallel P (raw.throw x) = raw.bind (raw.catch P (λx. )) (λx. )" (is ?thesis2)
proof -
  show ?thesis1
    by (simp add: raw.parallel_def raw.throw_def raw.bind_def raw.return_def raw.catch_def
                  prog.bind.bind prog.bind.return prog.bind.botL prog.parallel.bot
                  sum.case_distrib[where h="λf. prog.bind f (λx. )"]
                  sum.case_distrib[where h="λf. f  case_sum (prog.return  Inl) (λx. )"]
            cong: sum.case_cong)
  then show ?thesis2
    by (simp add: raw.parallel.commute)
qed

setup Sign.parent_path

setup Sign.parent_path

typedef ('s, 'x, 'v) exn = "UNIV :: ('s, 'x, 'v) raw.exn set"
by blast

setup_lifting type_definition_exn

instantiation exn :: (type, type, type) complete_distrib_lattice
begin

lift_definition bot_exn :: "('s, 'x, 'v) exn" is "" .
lift_definition top_exn :: "('s, 'x, 'v) exn" is "" .
lift_definition sup_exn :: "('s, 'x, 'v) exn  ('s, 'x, 'v) exn  ('s, 'x, 'v) exn" is sup .
lift_definition inf_exn :: "('s, 'x, 'v) exn  ('s, 'x, 'v) exn  ('s, 'x, 'v) exn" is inf .
lift_definition less_eq_exn :: "('s, 'x, 'v) exn  ('s, 'x, 'v) exn  bool" is less_eq .
lift_definition less_exn :: "('s, 'x, 'v) exn  ('s, 'x, 'v) exn  bool" is less .
lift_definition Inf_exn :: "('s, 'x, 'v) exn set  ('s, 'x, 'v) exn" is Inf .
lift_definition Sup_exn :: "('s, 'x, 'v) exn set  ('s, 'x, 'v) exn" is Sup .

instance by standard (transfer; auto intro: Inf_lower InfI le_supI1 SupI SupE Inf_Sup)+

end

setup Sign.mandatory_path "exn"

lift_definition action :: "('v × 's × 's) set  ('s, 'x, 'v) exn" is raw.action .
lift_definition return :: "'v  ('s, 'x, 'v) exn" is raw.return .
lift_definition throw :: "'x  ('s, 'x, 'v) exn" is raw.throw .
lift_definition catch :: "('s, 'x, 'v) exn  ('x  ('s, 'x, 'v) exn)  ('s, 'x, 'v) exn" is raw.catch .
lift_definition bind :: "('s, 'x, 'v) exn  ('v  ('s, 'x, 'v) exn)  ('s, 'x, 'v) exn" is raw.bind .
lift_definition parallel :: "('s, 'x, unit) exn  ('s, 'x, unit) exn  ('s, 'x, unit) exn" is raw.parallel .

adhoc_overloading
  Monad_Syntax.bind exn.bind
adhoc_overloading
  parallel exn.parallel

setup Sign.mandatory_path "bind"

lemma bind:
  shows "f  g  h = exn.bind f (λx. g x  h)"
by transfer (rule raw.bind.bind)

lemma return:
  shows returnL: "(⤜) (exn.return v) = (λg. g v)" (is ?thesis1)
    and returnR: "f  exn.return = f" (is ?thesis2)
by (transfer; rule raw.bind.return)+

lemma throwL:
  shows "(⤜) (exn.throw x) = (λg. exn.throw x)"
by transfer (rule raw.bind.throwL)

setup Sign.parent_path

setup Sign.mandatory_path "catch"

lemma catch:
  shows "exn.catch (exn.catch f handler1) handler2 = exn.catch f (λx. exn.catch (handler1 x) handler2)"
by transfer (rule raw.catch.catch)

lemma returnL:
  shows "exn.catch (exn.return v) = (λhandler. exn.return v)"
by transfer (rule raw.catch.returnL)

lemma throw:
  shows throwL: "exn.catch (exn.throw x) = (λg. g x)"
    and throwR: "exn.catch f exn.throw = f"
by (transfer; rule raw.catch.throw)+

setup Sign.parent_path

setup Sign.mandatory_path "parallel"

lemma commute:     
  shows "exn.parallel P Q = exn.parallel Q P"
by transfer (rule raw.parallel.commute)

lemma assoc:
  shows "exn.parallel P (exn.parallel Q R) = exn.parallel (exn.parallel P Q) R"
by transfer (rule raw.parallel.assoc)

lemma return:
  shows returnL: "exn.return ()  P = exn.catch P "
    and returnR: "P  exn.return () = exn.catch P "
unfolding bot_fun_def by (transfer; rule raw.parallel.return)+

lemma throw:
  shows throwL: "exn.throw x  P = exn.catch P   "
    and throwR: "P  exn.throw x = exn.catch P   "
unfolding bot_fun_def by (transfer; rule raw.parallel.throw)+

setup Sign.parent_path

setup Sign.parent_path
(*<*)

end
(*>*)