POPL Tutorial/Properties of Typing and Reduction
From The Twelf Project
This problem (or problems) involves proving three properties of typing and reduction for the language L{num str} from Bob Harper's book, Practical Foundations for Programming Languages.
Contents |
[edit] The System L{num str}
Natural numbers nat : type. 0 : nat. s : nat -> nat. Addition for natural numbers plus_op : nat -> nat -> nat -> type. plus_op/0 : plus_op 0 N N. plus_op/s : plus_op N M L -> plus_op (s N) M (s L). Multiplication for natural numbers times_op : nat -> nat -> nat -> type. times_op/0 : times_op 0 N 0. times_op/s : times_op (s N) M P <- times_op N M L <- plus_op L M P. %%%%%%%%%%%%%%% L{num str}: Syntax %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Types typ : type. num : typ. str : typ. Expressions. For simplicity, strings are just natural numbers, concatenation is addition, and len is the identity. exp : type. nume : nat -> exp. stre : nat -> exp. plus : exp -> exp -> exp. times : exp -> exp -> exp. cat : exp -> exp -> exp. len : exp -> exp. let : exp -> (exp -> exp) -> exp. %%%%%%%%%%%%%%% L{num str}: Static semantics (typing judgment) %%%%%%%%%%%%%%% of : exp -> typ -> type. of/stre : of (stre S) str. of/nume : of (nume N) num. of/plus : of E1 num -> of E2 num -> of (plus E1 E2) num. of/times : of E1 num -> of E2 num -> of (times E1 E2) num. of/cat : of E1 str -> of E2 str -> of (cat E1 E2) str. of/len : of E1 str -> of (len E1) num. of/let : of E1 T1 -> ({x} of x T1 -> of (E2 x) T2) -> of (let E1 ([x] E2 x)) T2. Assumption block for typing judgment (coming from of/let) %block of_bind : some {T:typ} block {x:exp}{ofx:of x T}. %%%%%%%%%%%%%%% L{num str}: Dynamic Semantics %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Values val : exp -> type. val/stre : val (stre N). val/nume : val (nume N). Reduction red : exp -> exp -> type. red/plus/num : plus_op N1 N2 N -> red (plus (nume N1) (nume N2)) (nume N). red/plus1 : red E1 E1' -> red (plus E1 E2) (plus E1' E2). red/plus2 : val E1 -> red E2 E2' -> red (plus E1 E2) (plus E1 E2'). red/times/num : times_op N1 N2 N -> red (times (nume N1) (nume N2)) (nume N). red/times1 : red E1 E1' -> red (times E1 E2) (times E1' E2). red/times2 : val E1 -> red E2 E2' -> red (times E1 E2) (times E1 E2'). red/cat/str : plus_op S1 S2 S -> red (cat (stre S1) (stre S2)) (stre S). red/cat1 : red E1 E1' -> red (cat E1 E2) (cat E1' E2). red/cat2 : val E1 -> red E2 E2' -> red (cat E1 E2) (cat E1 E2'). red/len/str : red (len (stre S)) (nume S). red/len : red E1 E1' -> red (len E1) (len E1'). red/let/val : val E1 -> red (let E1 ([x] E2 x)) (E2 E1). red/let : red E1 E1' -> red (let E1 ([x] E2 x)) (let E1' ([x] E2 x)).
[edit] Problem 1: Unicity of Typing
%%%%%%%%%%%%%%% Lemma 9.1 (Unicity of typing) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % If G |- E : T1 and G |- E : T2, then T1 = T2. Equality of types eqtyp : typ -> typ -> type. refl_t : eqtyp T T. Congruence for typing assumptions. Although the proof doesn't introduce any parameters or hypotheses, it is used by a theorem that does, and so we need to check it in the extended worlds. cong_of : eqtyp A1 A2 -> ({x} of x A1 -> of (E x) T) -> ({x} of x A2 -> of (E x) T) -> type. %mode cong_of +EA +OE1 -OE2. - : cong_of refl_t OE1 OE1. %worlds (of_bind) (cong_of _ _ _). %total OE1 (cong_of _ OE1 _). Statement and proof of Lemma. Notice that the worlds in this proof are an extension (technically, they subsume) the worlds in the congruence lemma above. lemma9-1 : of E T1 -> of E T2 -> eqtyp T1 T2 -> type. %mode lemma9-1 +OjE1 +OjE2 -Ej. - : lemma9-1 of/stre of/stre refl_t. - : lemma9-1 of/nume of/nume refl_t. - : lemma9-1 (of/plus OjE11 OjE12) (of/plus OjE21 OjE22) refl_t. - : lemma9-1 (of/times OjE11 OjE12) (of/times OjE21 OjE22) refl_t. - : lemma9-1 (of/cat OjE11 OjE12) (of/cat OjE21 OjE22) refl_t. - : lemma9-1 (of/len OjE1) (of/len OjE2) refl_t. - : lemma9-1 (of/let OjE11 ([x][ofx1] OjE12 x ofx1)) (of/let OjE21 ([x][ofx2] OjE22 x ofx2)) Q <- lemma9-1 OjE11 OjE21 E1 <- cong_of E1 OjE12 OjE12' <- {x}{ofx2} lemma9-1 ofx2 ofx2 refl_t -> lemma9-1 (OjE12' x ofx2) (OjE22 x ofx2) Q. %block lemma_block : some {T:typ} block {x:exp}{ofx:of x T}{u:lemma9-1 ofx ofx refl_t}. %worlds (lemma_block) (lemma9-1 _ _ _). %total OjT2 (lemma9-1 _ OjT2 _).
[edit] Problem 2: Determinacy of Reduction
%%%%%%%%%%%%%%% Lemma 10.1 (Determinacy of Reduction) %%%%%%%%%%%%%%%%%%%%%%% % If E |-> E' and E |-> E'', then E' = E''. Equality and congruence for nats eqnat : nat -> nat -> type. refl_n : eqnat N N. cong_s : eqnat N M -> eqnat (s N) (s M) -> type. %mode cong_s +E -ES. - : cong_s refl_n refl_n. %worlds () (cong_s _ _). %total {} (cong_s _ _). Equality for expressions eqexp : exp -> exp -> type. refl_e : eqexp E E. Congruences for expressions cong_nume : eqnat N1 N2 -> eqexp (nume N1) (nume N2) -> type. %mode cong_nume +E -E'. - : cong_nume refl_n refl_e. %worlds () (cong_nume _ _). %total E (cong_nume E _). cong_stre : eqnat S1 S2 -> eqexp (stre S1) (stre S2) -> type. %mode cong_stre +E -E'. - : cong_stre refl_n refl_e. %worlds () (cong_stre _ _). %total E (cong_stre E _). cong_plus1 : eqexp E1 E2 -> eqexp (plus E1 F) (plus E2 F) -> type. %mode +{E1:exp} +{E2:exp} +{F:exp} +{E:eqexp E1 E2} -{E':eqexp (plus E1 F) (plus E2 F)} (cong_plus1 E E'). - : cong_plus1 refl_e refl_e. %worlds () (cong_plus1 _ _). %total E (cong_plus1 E _). cong_plus2 : eqexp F1 F2 -> eqexp (plus E F1) (plus E F2) -> type. %mode +{F1:exp} +{F2:exp} +{E:exp} +{E1:eqexp F1 F2} -{E':eqexp (plus E F1) (plus E F2)} (cong_plus2 E1 E'). - : cong_plus2 refl_e refl_e. %worlds () (cong_plus2 _ _). %total E (cong_plus2 E _). cong_times1 : eqexp E1 E2 -> eqexp (times E1 F) (times E2 F) -> type. %mode +{E1:exp} +{E2:exp} +{F:exp} +{E:eqexp E1 E2} -{E':eqexp (times E1 F) (times E2 F)} (cong_times1 E E'). - : cong_times1 refl_e refl_e. %worlds () (cong_times1 _ _). %total E (cong_times1 E _). cong_times2 : eqexp F1 F2 -> eqexp (times E F1) (times E F2) -> type. %mode +{F1:exp} +{F2:exp} +{E:exp} +{E2:eqexp F1 F2} -{E':eqexp (times E F1) (times E F2)} (cong_times2 E2 E'). - : cong_times2 refl_e refl_e. %worlds () (cong_times2 _ _). %total E (cong_times2 E _). cong_cat1 : eqexp E1 E2 -> eqexp (cat E1 F) (cat E2 F) -> type. %mode +{E1:exp} +{E2:exp} +{F:exp} +{E:eqexp E1 E2} -{E':eqexp (cat E1 F) (cat E2 F)} (cong_cat1 E E'). - : cong_cat1 refl_e refl_e. %worlds () (cong_cat1 _ _). %total E (cong_cat1 E _). cong_cat2 : eqexp F1 F2 -> eqexp (cat E F1) (cat E F2) -> type. %mode +{F1:exp} +{F2:exp} +{E:exp} +{E3:eqexp F1 F2} -{E':eqexp (cat E F1) (cat E F2)} (cong_cat2 E3 E'). - : cong_cat2 refl_e refl_e. %worlds () (cong_cat2 _ _). %total E (cong_cat2 E _). cong_len : eqexp E1 E2 -> eqexp (len E1) (len E2) -> type. %mode cong_len +E -E'. - : cong_len refl_e refl_e. %worlds () (cong_len _ _). %total E (cong_len E _). cong_let : eqexp E1 E2 -> eqexp (let E1 F) (let E2 F) -> type. %mode +{E1:exp} +{E2:exp} +{F:exp -> exp} +{E:eqexp E1 E2} -{E':eqexp (let E1 ([x:exp] F x)) (let E2 ([x:exp] F x))} (cong_let E E'). - : cong_let refl_e refl_e. %worlds () (cong_let _ _). %total E (cong_let E _). Uniqueness of plus plus! : plus_op N M L1 -> plus_op N M L2 -> eqnat L1 L2 -> type. %mode plus! +Pj1 +Pj2 -EL. - : plus! plus_op/0 plus_op/0 refl_n. - : plus! (plus_op/s Pj1) (plus_op/s Pj2) ES <- plus! Pj1 Pj2 EL <- cong_s EL ES. %worlds () (plus! _ _ _). %total Pj1 (plus! Pj1 _ _). Congruence of plus plus_cong : eqnat N1 N2 -> plus_op N1 M L1 -> plus_op N2 M L2 -> eqnat L1 L2 -> type. %mode plus_cong +EN +Pj1 +Pj2 -EL. - : plus_cong refl_n plus_op/0 plus_op/0 refl_n. - : plus_cong refl_n (plus_op/s Pj1) (plus_op/s Pj2) ES <- plus_cong refl_n Pj1 Pj2 EL <- cong_s EL ES. %worlds () (plus_cong _ _ _ _). %total PjL (plus_cong _ PjL _ _). Uniqueness of times times! : times_op N M L1 -> times_op N M L2 -> eqnat L1 L2 -> type. %mode times! +Tj1 +Tj2 -EL. - : times! times_op/0 times_op/0 refl_n. - : times! (times_op/s Pj1 Tj1) (times_op/s Pj2 Tj2) ES <- times! Tj1 Tj2 EL <- plus_cong EL Pj1 Pj2 ES. %worlds () (times! _ _ _). %total Tj1 (times! Tj1 _ _). Proof of Lemma 10.1 lemma10-1 : red E E1 -> red E E2 -> eqexp E1 E2 -> type. %mode lemma10-1 +RjE1 +RjE2 -EE. - : lemma10-1 (red/plus/num PjN1) (red/plus/num PjN2) EE' <- plus! PjN1 PjN2 EL <- cong_nume EL EE'. - : lemma10-1 (red/plus1 RjE1) (red/plus1 RjE2) EE' <- lemma10-1 RjE1 RjE2 EE <- cong_plus1 EE EE'. - : lemma10-1 (red/plus2 _ RjF1) (red/plus2 _ RjF2) EE' <- lemma10-1 RjF1 RjF2 EF <- cong_plus2 EF EE'. - : lemma10-1 (red/times/num TjN1) (red/times/num TjN2) EE' <- times! TjN1 TjN2 EE <- cong_nume EE EE'. - : lemma10-1 (red/times1 RjE1) (red/times1 RjE2) EE' <- lemma10-1 RjE1 RjE2 EE <- cong_times1 EE EE'. - : lemma10-1 (red/times2 _ RjF1) (red/times2 _ RjF2) EE' <- lemma10-1 RjF1 RjF2 EF <- cong_times2 EF EE'. - : lemma10-1 (red/cat/str PjN1) (red/cat/str PjN2) EE' <- plus! PjN1 PjN2 EE <- cong_stre EE EE'. - : lemma10-1 (red/cat1 RjE1) (red/cat1 RjE2) EE' <- lemma10-1 RjE1 RjE2 EE <- cong_cat1 EE EE'. - : lemma10-1 (red/cat2 _ RjF1) (red/cat2 _ RjF2) EE' <- lemma10-1 RjF1 RjF2 EF <- cong_cat2 EF EE'. - : lemma10-1 (red/len/str:red (len (stre S)) (nume S)) red/len/str EE' <- cong_nume refl_n EE'. - : lemma10-1 (red/len RjE1) (red/len RjE2) EE' <- lemma10-1 RjE1 RjE2 EE <- cong_len EE EE'. - : lemma10-1 (red/let/val VjE11) (red/let/val VjE12) refl_e. - : lemma10-1 (red/let RjE1) (red/let RjE2) EE' <- lemma10-1 RjE1 RjE2 EE <- cong_let EE EE'. %worlds () (lemma10-1 _ _ _). %total RjE (lemma10-1 RjE _ _).
[edit] Problem 3: Contextual Semantics
In this problem, we define the contextual semantics for L{num str} and proof that it is equivalent to (defines the same relation as) the given dynamic semantics (reduction).
%%%%%%%%%%%%%%% L{num str}: Contextual Semantics %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Instructions: E0 ~> E0' instr : exp -> exp -> type. instr/plus : plus_op N1 N2 N -> instr (plus (nume N1) (nume N2)) (nume N). instr/times : times_op N1 N2 N -> instr (times (nume N1) (nume N2)) (nume N). instr/cat : plus_op S1 S2 S -> instr (cat (stre S1) (stre S2)) (stre S). instr/len : instr (len (stre S)) (nume S). instr/let : val E1 -> instr (let E1 ([x] E2 x)) (E2 E1). Expression contexts, represented as "expressions with holes", i.e., functions on expressions. ectxt : (exp -> exp) -> type. ectxt/hole : ectxt ([x] x). ectxt/plus1 : ectxt ([x] C1 x) -> ectxt ([x] plus (C1 x) E2). ectxt/plus2 : val E1 -> ectxt ([x] C2 x) -> ectxt ([x] plus E1 (C2 x)). ectxt/times1 : ectxt ([x] C1 x) -> ectxt ([x] times (C1 x) E2). ectxt/times2 : val E1 -> ectxt ([x] C2 x) -> ectxt ([x] times E1 (C2 x)). ectxt/cat1 : ectxt ([x] C1 x) -> ectxt ([x] cat (C1 x) E2). ectxt/cat2 : val E1 -> ectxt ([x] C2 x) -> ectxt ([x] cat E1 (C2 x)). ectxt/len : ectxt ([x] C x) -> ectxt ([x] len (C x)). ectxt/let : ectxt ([x] C1 x) -> ectxt ([x] let (C1 x) ([y] E2 y)). Filling the hole of an expression context with an expression fill : ectxt ([x] C x) -> exp -> exp -> type. fill/hole : fill ectxt/hole E E. fill/plus1 : fill ECC1 E C1@E -> fill (ectxt/plus1 ECC1:ectxt ([x] plus (C1 x) E2)) E (plus C1@E E2). fill/plus2 : {VjE1:val E1} fill ECC2 E C2@E -> fill (ectxt/plus2 VjE1 ECC2) E (plus E1 C2@E). fill/times1 : fill ECC1 E C1@E -> fill (ectxt/times1 ECC1:ectxt ([x] times (C1 x) E2)) E (times C1@E E2). fill/times2 : {VjE1:val E1} fill ECC2 E C2@E -> fill (ectxt/times2 VjE1 ECC2) E (times E1 C2@E). fill/cat1 : fill ECC1 E C1@E -> fill (ectxt/cat1 ECC1:ectxt ([x] cat (C1 x) E2)) E (cat C1@E E2). fill/cat2 : {VjE1:val E1} fill ECC2 E C2@E -> fill (ectxt/cat2 VjE1 ECC2) E (cat E1 C2@E). fill/len : fill ECC1 E C1@E -> fill (ectxt/len ECC1) E (len C1@E). fill/let : fill ECC1 E C1@E -> fill (ectxt/let ECC1:ectxt ([x] let (C1 x) [y] E2 y)) E (let C1@E ([y] E2 y)). Contextual reduction rule cred : exp -> exp -> type. cred/step : fill EC E0 C@E0 -> instr E0 E0' -> fill EC E0' C@E0' -> cred C@E0 C@E0'. %%%%%%%%%%%%%%% Theorem 10.2.1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % If E |-> E', then E |->c E'. thm10-2-1 : red E E' -> cred E E' -> type. %mode thm10-2-1 +RjE -CjE. - : thm10-2-1 (red/plus/num PjN) (cred/step fill/hole (instr/plus PjN) fill/hole). - : thm10-2-1 (red/plus1 RjE1) (cred/step (fill/plus1 FjC1@E0) I (fill/plus1 FjC1@E0')) <- thm10-2-1 RjE1 (cred/step FjC1@E0 I FjC1@E0'). - : thm10-2-1 (red/plus2 VjE1 RjE2) (cred/step (fill/plus2 VjE1 FjC2@E0) I (fill/plus2 VjE1 FjC2@E0')) <- thm10-2-1 RjE2 (cred/step FjC2@E0 I FjC2@E0'). - : thm10-2-1 (red/times/num TjN) (cred/step fill/hole (instr/times TjN) fill/hole). - : thm10-2-1 (red/times1 RjE1) (cred/step (fill/times1 FjC1@E0) I (fill/times1 FjC1@E0')) <- thm10-2-1 RjE1 (cred/step FjC1@E0 I FjC1@E0'). - : thm10-2-1 (red/times2 VjE1 RjE2) (cred/step (fill/times2 VjE1 FjC2@E0) I (fill/times2 VjE1 FjC2@E0')) <- thm10-2-1 RjE2 (cred/step FjC2@E0 I FjC2@E0'). - : thm10-2-1 (red/cat/str PjN) (cred/step fill/hole (instr/cat PjN) fill/hole). - : thm10-2-1 (red/cat1 RjE1) (cred/step (fill/cat1 FjC1@E0) I (fill/cat1 FjC1@E0')) <- thm10-2-1 RjE1 (cred/step FjC1@E0 I FjC1@E0'). - : thm10-2-1 (red/cat2 VjE1 RjE2) (cred/step (fill/cat2 VjE1 FjC2@E0) I (fill/cat2 VjE1 FjC2@E0')) <- thm10-2-1 RjE2 (cred/step FjC2@E0 I FjC2@E0'). - : thm10-2-1 red/len/str (cred/step fill/hole instr/len fill/hole). - : thm10-2-1 (red/len RjE1) (cred/step (fill/len FjC1@E0) I (fill/len FjC1@E0')) <- thm10-2-1 RjE1 (cred/step FjC1@E0 I FjC1@E0'). - : thm10-2-1 (red/let/val VjE1) (cred/step fill/hole (instr/let VjE1) fill/hole). - : thm10-2-1 (red/let RjE1) (cred/step (fill/let FjC1@E0) I (fill/let FjC1@E0')) <- thm10-2-1 RjE1 (cred/step FjC1@E0 I FjC1@E0'). %worlds () (thm10-2-1 _ _). %total RjE (thm10-2-1 RjE _). %%%%%%%%%%%%%%% Theorem 10.2.2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % If E |->c E', then E |-> E'. thm10-2-2 : cred E E' -> red E E' -> type. %mode thm10-2-2 +CjE -RjE. Lemma. If C{E0} = E, E0 ~> E0', and C{E0'} = E', then E |-> E'. lem10-2-2 : fill EC E0 E -> instr E0 E0' -> fill EC E0' E' -> red E E' -> type. %mode lem10-2-2 +FjE +I +FjE' -RjE. - : lem10-2-2 fill/hole (instr/plus PjN) fill/hole (red/plus/num PjN). - : lem10-2-2 fill/hole (instr/times TjN) fill/hole (red/times/num TjN). - : lem10-2-2 fill/hole (instr/cat PjN) fill/hole (red/cat/str PjN). - : lem10-2-2 fill/hole instr/len fill/hole red/len/str. - : lem10-2-2 fill/hole (instr/let VjE1) fill/hole (red/let/val VjE1). - : lem10-2-2 (fill/plus1 FjC1@E0) I (fill/plus1 FjC1@E0') (red/plus1 RjE) <- lem10-2-2 FjC1@E0 I FjC1@E0' RjE. - : lem10-2-2 (fill/plus2 VjE1 FjC2@E0) I (fill/plus2 VjE1 FjC2@E0') (red/plus2 VjE1 RjE) <- lem10-2-2 FjC2@E0 I FjC2@E0' RjE. - : lem10-2-2 (fill/times1 FjC1@E0) I (fill/times1 FjC1@E0') (red/times1 RjE) <- lem10-2-2 FjC1@E0 I FjC1@E0' RjE. - : lem10-2-2 (fill/times2 VjE1 FjC2@E0) I (fill/times2 VjE1 FjC2@E0') (red/times2 VjE1 RjE) <- lem10-2-2 FjC2@E0 I FjC2@E0' RjE. - : lem10-2-2 (fill/cat1 FjC1@E0) I (fill/cat1 FjC1@E0') (red/cat1 RjE) <- lem10-2-2 FjC1@E0 I FjC1@E0' RjE. - : lem10-2-2 (fill/cat2 VjE1 FjC2@E0) I (fill/cat2 VjE1 FjC2@E0') (red/cat2 VjE1 RjE) <- lem10-2-2 FjC2@E0 I FjC2@E0' RjE. - : lem10-2-2 (fill/len FjC1@E0) I (fill/len FjC1@E0') (red/len RjE) <- lem10-2-2 FjC1@E0 I FjC1@E0' RjE. - : lem10-2-2 (fill/let FjC2@E0) I (fill/let FjC2@E0') (red/let RjE) <- lem10-2-2 FjC2@E0 I FjC2@E0' RjE. %worlds () (lem10-2-2 _ _ _ _). %total FjE (lem10-2-2 FjE _ _ _). Proof of main theorem - : thm10-2-2 (cred/step FjC@E0 I FjC@E0') RjE <- lem10-2-2 FjC@E0 I FjC@E0' RjE. %worlds () (thm10-2-2 _ _). %total {} (thm10-2-2 _ _).
[edit] Twelf Output
The output for the above.