Theory Continuations
theory Continuations
imports
  HOLCF
  Maybe
  Nats
  WorkerWrapperNew
begin
section‹Tagless interpreter via double-barreled continuations›
text‹\label{sec:continuations}›
type_synonym 'a Cont = "('a → 'a) → 'a"
definition
  val2cont :: "'a → 'a Cont" where
  "val2cont ≡ (Λ a c. c⋅a)"
definition
  cont2val :: "'a Cont → 'a" where
  "cont2val ≡ (Λ f. f⋅ID)"
lemma cont2val_val2cont_id: "cont2val oo val2cont = ID"
  by (rule cfun_eqI, simp add: val2cont_def cont2val_def)
domain Expr =
    Val (lazy val::"Nat")
  | Add (lazy addl::"Expr") (lazy addr::"Expr")
  | Throw
  | Catch (lazy cbody::"Expr") (lazy chandler::"Expr")
fixrec eval :: "Expr → Nat Maybe"
where
  "eval⋅(Val⋅n) = Just⋅n"
| "eval⋅(Add⋅x⋅y) = mliftM2 (Λ a b. a + b)⋅(eval⋅x)⋅(eval⋅y)"
| "eval⋅Throw = mfail"
| "eval⋅(Catch⋅x⋅y) = mcatch⋅(eval⋅x)⋅(eval⋅y)"
fixrec eval_body :: "(Expr → Nat Maybe) → Expr → Nat Maybe"
where
  "eval_body⋅r⋅(Val⋅n) = Just⋅n"
| "eval_body⋅r⋅(Add⋅x⋅y) = mliftM2 (Λ a b. a + b)⋅(r⋅x)⋅(r⋅y)"
| "eval_body⋅r⋅Throw = mfail"
| "eval_body⋅r⋅(Catch⋅x⋅y) = mcatch⋅(r⋅x)⋅(r⋅y)"
lemma eval_body_strictExpr[simp]: "eval_body⋅r⋅⊥ = ⊥"
  by (subst eval_body.unfold, simp)
lemma eval_eval_body_eq: "eval = fix⋅eval_body"
  by (rule cfun_eqI, subst eval_def, subst eval_body.unfold, simp)
subsection‹Worker/wrapper›
definition
  unwrapC :: "(Expr → Nat Maybe) → (Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe)" where
  "unwrapC ≡ Λ g e s f. case g⋅e of Nothing ⇒ f | Just⋅n ⇒ s⋅n"
lemma unwrapC_strict[simp]: "unwrapC⋅⊥ = ⊥"
  unfolding unwrapC_def by (rule cfun_eqI)+ simp
definition
  wrapC :: "(Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe) → (Expr → Nat Maybe)" where
  "wrapC ≡ Λ g e. g⋅e⋅Just⋅Nothing"
lemma wrapC_unwrapC_id: "wrapC oo unwrapC = ID"
proof(intro cfun_eqI)
  fix g e
  show "(wrapC oo unwrapC)⋅g⋅e = ID⋅g⋅e"
    by (cases "g⋅e", simp_all add: wrapC_def unwrapC_def)
qed
definition
  eval_work :: "Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe" where
  "eval_work ≡ fix⋅(unwrapC oo eval_body oo wrapC)"
definition
  eval_wrap :: "Expr → Nat Maybe" where
  "eval_wrap ≡ wrapC⋅eval_work"
fixrec eval_body' :: "(Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe)
                    → Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe"
where
  "eval_body'⋅r⋅(Val⋅n)⋅s⋅f = s⋅n"
| "eval_body'⋅r⋅(Add⋅x⋅y)⋅s⋅f = (case wrapC⋅r⋅x of
                                     Nothing ⇒ f
                                   | Just⋅n ⇒ (case wrapC⋅r⋅y of
                                                    Nothing ⇒ f
                                                  | Just⋅m ⇒ s⋅(n + m)))"
| "eval_body'⋅r⋅Throw⋅s⋅f = f"
| "eval_body'⋅r⋅(Catch⋅x⋅y)⋅s⋅f = (case wrapC⋅r⋅x of
                                       Nothing ⇒ (case wrapC⋅r⋅y of
                                                      Nothing ⇒ f
                                                    | Just⋅n ⇒ s⋅n)
                                     | Just⋅n ⇒ s⋅n)"
lemma eval_body'_strictExpr[simp]: "eval_body'⋅r⋅⊥⋅s⋅f = ⊥"
  by (subst eval_body'.unfold, simp)
definition
  eval_work' :: "Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe" where
  "eval_work' ≡ fix⋅eval_body'"
text‹This proof is unfortunately quite messy, due to the
simplifier's inability to cope with HOLCF's case distinctions.›
lemma eval_body'_eval_body_eq: "eval_body' = unwrapC oo eval_body oo wrapC"
  apply (intro cfun_eqI)
  apply (unfold unwrapC_def wrapC_def)
  apply (case_tac xa)
      apply simp_all
    apply (simp add: wrapC_def)
    apply (case_tac "x⋅Expr1⋅Just⋅Nothing")
     apply simp_all
    apply (case_tac "x⋅Expr2⋅Just⋅Nothing")
     apply simp_all
   apply (simp add: mfail_def)
  apply (simp add: mcatch_def wrapC_def)
  apply (case_tac "x⋅Expr1⋅Just⋅Nothing")
   apply simp_all
  done
fixrec eval_body_final :: "(Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe)
                         → Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe"
where
  "eval_body_final⋅r⋅(Val⋅n)⋅s⋅f = s⋅n"
| "eval_body_final⋅r⋅(Add⋅x⋅y)⋅s⋅f = r⋅x⋅(Λ n. r⋅y⋅(Λ m. s⋅(n + m))⋅f)⋅f"
| "eval_body_final⋅r⋅Throw⋅s⋅f = f"
| "eval_body_final⋅r⋅(Catch⋅x⋅y)⋅s⋅f = r⋅x⋅s⋅(r⋅y⋅s⋅f)"
lemma eval_body_final_strictExpr[simp]: "eval_body_final⋅r⋅⊥⋅s⋅f = ⊥"
  by (subst eval_body_final.unfold, simp)
lemma eval_body'_eval_body_final_eq: "eval_body_final oo unwrapC oo wrapC = eval_body'"
  apply (rule cfun_eqI)+
  apply (case_tac xa)
     apply (simp_all add: unwrapC_def)
  done
definition
  eval_work_final :: "Expr → (Nat → Nat Maybe) → Nat Maybe → Nat Maybe" where
  "eval_work_final ≡ fix⋅eval_body_final"
definition
  eval_final :: "Expr → Nat Maybe" where
  "eval_final ≡ (Λ e. eval_work_final⋅e⋅Just⋅Nothing)"
lemma "eval = eval_final"
proof -
  have "eval = fix⋅eval_body" by (rule eval_eval_body_eq)
  also from wrapC_unwrapC_id unwrapC_strict have "… = wrapC⋅(fix⋅eval_body_final)"
    apply (rule worker_wrapper_fusion_new)
    using eval_body'_eval_body_final_eq eval_body'_eval_body_eq by simp
  also have "… = eval_final"
    unfolding eval_final_def eval_work_final_def wrapC_def
    by simp
  finally show ?thesis .
qed
end