section‹Relating direct and continuation semantics› (*<*) theory Continuations imports
PCF begin
(*>*) text‹
label{sec:continuations}
is a fairly literal version of 🍋‹"DBLP:conf/icalp/Reynolds74"›, adapted to untyped PCF. A more
account has been given by 🍋‹"DBLP:journals/tcs/Filinski07"› in terms of a monadic meta
, which is difficult to model in Isabelle (but see 🍋‹"Huffman:MonadTransformers:2012"›).
begin by giving PCF a continuation semantics following the modern
of 🍋‹"wadler92:_essence_of_funct_progr"›. We use the
function space ‹('o ValK, 'o) K → ('o ValK, 'o) K›
our language includes call-by-name.
›
type_synonym ('a, 'o) K = "('a → 'o) → 'o"
domain 'o ValK
= ValKF (lazy appKF :: "('o ValK, 'o) K → ('o ValK, 'o) K")
| ValKTT | ValKFF
| ValKN (lazy"nat")
definition
condK :: "'o ValKM → 'o ValKM → 'o ValKM → 'o ValKM" where "condK ≡ Λ iK tK eK. bindK⋅iK⋅(Λ i. case i of ValKF⋅f ==>⊥ | ValKTT ==> tK | ValKFF ==> eK | ValKN⋅n ==>⊥)"
definition succK :: "'o ValKM → 'o ValKM"where "succK ≡ Λ nK. bindK⋅nK⋅(Λ (ValKN⋅n). unitK⋅(ValKN⋅(n + 1)))"
definition predK :: "'o ValKM → 'o ValKM"where "predK ≡ Λ nK. bindK⋅nK⋅(Λ (ValKN⋅n). case n of 0 ==>⊥ | Suc n ==> unitK⋅(ValKN⋅n))"
definition isZeroK :: "'o ValKM → 'o ValKM"where "isZeroK ≡ Λ nK. bindK⋅nK⋅(Λ (ValKN⋅n). unitK⋅(if n = 0 then ValKTT else ValKFF))"
text‹
continuation semantics for PCF. If we had defined our direct
using a monad then the correspondence would be more
obvious.
establish the chain completeness (admissibility) of our logical
, we need to show that @{term "unitK"} is an \emph{order
}, i.e., if @{term "unitK⋅x ⊑ unitK⋅y"} then @{term "x ⊑
"}. This is an order-theoretic version of injectivity.
order to define a continuation that witnesses this, we need to be
to distinguish converging and diverging computations. We
require our observation domain to contain at least two
:
🍋‹"DBLP:conf/icalp/Reynolds74"› and 🍋‹‹Remark › in "DBLP:journals/tcs/Filinski07"› we use the following continuation:
›
lemma cont_below [simp, cont2cont]: "cont (λx::'a::pcpo. if x ⊑ d then ⊥ else c)" (*<*) proof(rule contI2) show"monofun (λx. if x ⊑ d then ⊥ else c)" apply (rule monofunI) apply clarsimp apply (cut_tac x=x and y=y and z=d in below_trans) apply auto done next fix Y :: "nat ==> 'a::pcpo" assume Y: "chain Y" assume"chain (λi. if Y i ⊑ d then ⊥ else c)" show"(if (⊔ i. Y i) ⊑ d then ⊥ else c) ⊑ (⊔ i. if Y i ⊑ d then ⊥ else c)" proof(cases "∀i. Y i ⊑ d") case True hence"Lub Y ⊑ d" using lub_below_iff[OF Y] by simp thus ?thesis by simp next case False let ?f = "λi. if Y i ⊑ d then ⊥ else c" from False have LubY: "¬ Lub Y ⊑ d" using lub_below_iff[OF Y] by simp from False have F: "chain ?f" apply - apply (rule chainI) apply clarsimp apply (cut_tac i=i and j="Suc i"in chain_mono[OF Y]) apply clarsimp apply (cut_tac x="Y i"and y="Y (Suc i)"and z=d in below_trans) apply simp_all done from False obtain i where Yi: "¬ Y i ⊑ d"by blast hence M: "max_in_chain i ?f" apply - apply (rule max_in_chainI) apply clarsimp apply (drule chain_mono[OF Y]) apply (cut_tac x="Y i"and y="Y j"and z=d in below_trans) apply simp_all done from LubY Yi show ?thesis using iffD1[OF maxinch_is_thelub, OF F M] by simp qed qed (*>*) text‹›
lemma (in at_least_two_elements) below_monic_unitK [intro, simp]: "below_monic_cfun (unitK :: 'o ValK → 'o ValKM)" proof(rule below_monicI) fix v v' :: "'o ValK" assume vv': "unitK⋅v ⊑ unitK⋅v'" let ?k = "Λ x. if x ⊑ v' then ⊥ else some_non_bottom_element" from vv' have"unitK⋅v⋅?k ⊑ unitK⋅v'⋅?k"by (rule monofun_cfun_fun) hence"?k⋅v ⊑ ?k⋅v'"by (simp add: unitK_def) with some_non_bottom_element show"v ⊑ v'"by (auto split: if_split_asm) qed
subsection‹Logical relation›
text‹
follow 🍋‹"DBLP:conf/icalp/Reynolds74"› by simultaneously
a pair of relations over values and functions. Both are
-reflecting, in contrast to the situation for computational
in \S\ref{sec:compad}. 🍋‹"DBLP:journals/tcs/Filinski07"›
by assuming that values are always defined, and relates values
monadic computations.
›
type_synonym 'o lfr = "(ValD, 'o ValKM, ValD → ValD, 'o ValKM → 'o ValKM) lf_pair_rep" type_synonym 'o lflf = "(ValD, 'o ValKM, ValD → ValD, 'o ValKM → 'o ValKM) lf_pair"
context at_least_two_elements begin
abbreviation lr_eta_rep_N where "lr_eta_rep_N ≡ { (e, e') . (e = ⊥∧ e' = ⊥) ∨ (e = ValTT ∧ e' = unitK⋅ValKTT) ∨ (e = ValFF ∧ e' = unitK⋅ValKFF) ∨ (∃n. e = ValN⋅n ∧ e' = unitK⋅(ValKN⋅n)) }"
abbreviation lr_eta_rep_F where "lr_eta_rep_F ≡ λ(rm, rp). { (e, e') . (e = ⊥∧ e' = ⊥) ∨ (∃f f'. e = ValF⋅f ∧ e' = unitK⋅(ValKF⋅f') ∧ (f, f') ∈ unlr (snd rp)) }"
definition lr_eta_rep where "lr_eta_rep ≡ λr. lr_eta_rep_N ∪ lr_eta_rep_F r"
lemma mono_lr: shows"mono (lr :: 'o lflf)" apply (rule monoI) apply simp apply (simp add: lr_rep_def) apply (rule conjI) apply (force simp: lr_eta_rep_def split_def dual_less_eq_iff unlr_leq[symmetric]) (* FIXME stuck with the projections on the product *) apply (auto simp: lr_theta_rep_def split_def dual_less_eq_iff unlr_leq[symmetric]) apply (drule_tac x="(ae, bc)"in bspec) apply (case_tac a) apply (case_tac ab) apply (auto simp: unlr_leq[symmetric]) done
(*>*) end(* context at_least_two_elements *)
text‹
takes some effort to set up the minimal invariant relating the two
of domains. One might hope this would be easier using deflations
which might compose) rather than ``copy'' functions (which certainly
't).
elide these as they are tedious.
› (*<*)
primrec
ValD_copy_i :: "nat ==> ValD → ValD" where "ValD_copy_i 0 = ⊥"
| "ValD_copy_i (Suc n) = (Λ v. case v of ValF⋅f ==> ValF⋅(ValD_copy_i n oo f oo ValD_copy_i n) | ValTT ==> ValTT | ValFF ==> ValFF | ValN⋅m ==> ValN⋅m)"
primrec
ValK_copy_i :: "nat ==> 'o ValK → 'o ValK" where "ValK_copy_i 0 = ⊥"
| "ValK_copy_i (Suc n) = (Λ v. case v of ValKF⋅f ==> ValKF⋅(cfun_map⋅(KM_map⋅(ValK_copy_i n))⋅(KM_map⋅(ValK_copy_i n))⋅f) | ValKTT ==> ValKTT | ValKFF ==> ValKFF | ValKN⋅m ==> ValKN⋅m)"
abbreviation "ValK_copy ≡ (⊔i. ValK_copy_i i)"
lemma ValK_copy_chain [intro, simp]: "chain (ValK_copy_i :: nat ==> 'o ValK → 'o ValK)" proof(rule chainI) fix i show"ValK_copy_i i ⊑ (ValK_copy_i (Suc i) :: 'o ValK → 'o ValK)" proof(induct i) case (Suc i)
{ fix x :: "'o ValK" have"ValK_copy_i (Suc i)⋅x ⊑ ValK_copy_i (Suc (Suc i))⋅x" proof(cases x) case (ValKF f) with Suc show ?thesis by (clarsimp simp: monofun_cfun KM_map_def) qed simp_all } thus ?caseby (simp add: cfun_below_iff) qed simp qed
lemma ValK_copy_fix: "ValK_copy = (ID :: 'o ValK → 'o ValK)" proof -
{ fix x :: "'o ValK" fix i :: nat have"ValK_take i⋅(ValK_copy_i i⋅(ValK_take i⋅x)) = ValK_take i⋅x" proof (induct i arbitrary: x) case (Suc n) thus ?case by (cases x) (simp_all add: KM_map_def cfun_map_def) qed simp } hence"∧x :: 'o ValK. (⊔i. ValK_take i⋅(ValK_copy_i i⋅(ValK_take i⋅x))) = (⊔i. ValK_take i⋅x)" by (blast intro: lub_eq) thus ?thesis by (simp add: lub_distribs ValK.lub_take cfun_eq_iff) qed
lemma fix_ValD_copy_rec_ID: "fix⋅ValD_copy_rec = (ID, ID)" using ValD_copy_rec_ValD_copy_lub ValD_copy_lub_ID cfun_map_ID by simp
fixrec
ValK_copy_rec :: "(('o ValKM → 'o ValKM) × (('o ValKM → 'o ValKM) → ('o ValKM → 'o ValKM))) → ('o ValKM → 'o ValKM) × (('o ValKM → 'o ValKM) → ('o ValKM → 'o ValKM))" where "ValK_copy_rec⋅r = (Λ vm. KM_map⋅(Λ v. case v of ValKF⋅f ==> ValKF⋅(snd r⋅f) | ValKTT ==> ValKTT | ValKFF ==> ValKFF | ValKN⋅a ==> ValKN⋅a)⋅vm, Λ f. cfun_map⋅(strictify⋅(fst r))⋅(strictify⋅(fst r))⋅f)"
abbreviation
ValK_copy_eta where "ValK_copy_eta i ≡ fst (iterate i⋅ValK_copy_rec⋅⊥)"
abbreviation
ValK_copy_theta where "ValK_copy_theta i ≡ snd (iterate i⋅ValK_copy_rec⋅⊥)"
lemma ValK_copy_strict [intro, simp]: "ValK_copy_eta n⋅⊥ = (⊥ :: 'o ValKM)" "ValK_copy_theta n⋅⊥ = (⊥ :: 'o ValKM → 'o ValKM)" by (induct n) (simp_all add: cfun_map_def)
sublocale value_retraction < at_least_two_elements "VtoO⋅(ValKN⋅0)" using OV by - (standard, simp add: injection_defined cfcomp1 cfun_eq_iff)
context value_retraction begin
fun
DtoKM_i :: "nat ==> ValD → 'o ValKM" and
KMtoD_i :: "nat ==> 'o ValKM → ValD" where "DtoKM_i 0 = ⊥"
| "DtoKM_i (Suc n) = (Λ v. case v of ValF⋅f ==> unitK⋅(ValKF⋅(cfun_map⋅(KMtoD_i n)⋅(DtoKM_i n)⋅f)) | ValTT ==> unitK⋅ValKTT | ValFF ==> unitK⋅ValKFF | ValN⋅m ==> unitK⋅(ValKN⋅m))"
lemma DtoKM_KMtoD_chain [intro, simp]: "chain DtoKM_i" "chain KMtoD_i" proof - let ?C = "λi. (DtoKM_i i, KMtoD_i i)" have"chain ?C" proof(rule chainI) fix i show"?C i ⊑ ?C (Suc i)" proof(induct i) case (Suc i) show ?case proof(rule monofun_pair) show"DtoKM_i (Suc i) ⊑ DtoKM_i (Suc (Suc i))" proof(rule cfun_belowI) fix x from Suc show"DtoKM_i (Suc i)⋅x ⊑ DtoKM_i (Suc (Suc i))⋅x" by (cases x) (auto intro!: monofun_cfun simp: cfun_map_def cfun_below_iff) qed show"KMtoD_i (Suc i) ⊑ KMtoD_i (Suc (Suc i))" proof(rule cfun_belowI) fix x from Suc show"KMtoD_i (Suc i)⋅x ⊑ KMtoD_i (Suc (Suc i))⋅x" apply (simp add: eta_cfun) apply (intro monofun_cfun_fun monofun_cfun_arg) apply (intro cfun_belowI) apply (auto intro: monofun_cfun) done qed qed qed simp qed thenshow"chain DtoKM_i""chain KMtoD_i" by (auto dest: ch2ch_fst ch2ch_snd) qed (*>*)
text‹
1 from 🍋‹"DBLP:conf/icalp/Reynolds74"›.
›
lemma Lemma1: "η: x ↦ DtoKM⋅x" "η: x ↦ x' ==> x = KMtoD⋅x'" (*<*) proof - have K: "η: ValD_copy_i i⋅x ↦ DtoKM_i i⋅x" and L: "η: x ↦ x' ==> ValD_copy_i i⋅x = KMtoD_i i⋅x'"for x x' i proof(induct i arbitrary: x x') case (Suc i)
{ case1show ?case apply (cases x) apply simp_all apply (rule eta_F) apply (rule theta_F) using Suc apply simp done }
{ case2thus ?case apply (induct rule: eta_induct) using OV apply (simp_all add: cfun_eq_iff retraction_strict) apply (clarsimp simp: cfun_eq_iff) apply (erule theta_induct) using Suc apply simp done } qed simp_all let ?C1 = "λi. (ValD_copy_i i, DtoKM_i i)" let ?P1 = "λf. η: (fst f)⋅x ↦ (snd f)⋅x" have"adm ?P1"by (rule adm_subst) simp_all with K have"?P1 (⊔i. ValD_copy_i i, ⊔i. DtoKM_i i)" using admD[where P="?P1"and Y="?C1"] lub_prod[where S="?C1"] by simp moreover
{ fix x :: ValD fix x' :: "'o ValKM" let ?C2 = "λi. (ValD_copy_i i, KMtoD_i i)" let ?P2 = "λf. (fst f)⋅x = (snd f)⋅x'" have"adm (λf. ?P2 f)"by simp with L have"η: x ↦ x' ==> ?P2 (⊔i. ValD_copy_i i, ⊔i. KMtoD_i i)" using admD[where P="?P2"and Y="?C2"] lub_prod[where S="?C2"] by simp } ultimatelyshow "η: x ↦ DtoKM⋅x" "η: x ↦ x' ==> x = KMtoD⋅x'" by (simp_all add: ValD_copy_lub_ID) qed
(*>*) text‹
2 from 🍋‹"DBLP:conf/icalp/Reynolds74"›.
›
theorem Theorem2: "evalD e⋅ρ = KMtoD⋅(evalK e⋅(DtoKM oo ρ))" using Lemma1(2)[OF Theorem1] Lemma1(1) by (simp add: cfcomp1)
end
text‹
🍋‹‹Remark~48› in "DBLP:journals/tcs/Filinski07"› observes that there
not be a retraction between direct and continuation semantics for
with richer notions of effects.
should be routine to extend the above approach to the higher-order
language of 🍋‹"DBLP:conf/icfp/WandV04"›.
wonder if it is possible to construct continuation semantics from
semantics as proposed by 🍋‹"DBLP:journals/jacm/SethiT80"›. Roughly we might hope to lift a
between two value domains to a retraction at higher types
synthesising a suitable logical relation.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.