Notes on Evaluation Contexts & Type Safety Syntax: t ::= bool | t1 -> t2 e ::= x | v | if e1 then e2 else e3 | e1 e2 v ::= true | false | \x:t.e E ::= [] | E e | v E | if E then e1 else e2 Operational rules: --------------------- (\x:t.e) v -> e[v/x] ----------------------------- (If-true) if true then e1 else e2 -> e1 ------------------------------ (If-false) if false then e1 else e2 -> e2 e -> e' -------------- (E-context) E[e] -> E[e'] Example: if (if ((\x: bool.x) true) then e1 else e2) then e3 else e4 E = if (if [] then e1 else e2) then e3 else e4 e = (\x: bool.x) true e -> true --------------- E[e] -> E[true] Lemma 1. if G |- E : t1 ==> t2, and G |- e : t1 then G |- E[e] : t2 Lemma 2. if G |- E[e] : t2 then G |- e : t1 and G |- E : t1 ==> t2 (Proved last time) Preservation: if |- e : t and e -> e' then |- e' : t Case: (1) e1 -> e1' ----------------- (Note: e = E[e1] and e' = E[e1']) E[e1] -> E[e1'] (2) |- E[e1] : t (Assumption) (3) |- e1 : t1 (Lemma 2) (4) |- E : t1 ==> t (Lemma 2) (5) |- e1' : t1 (1, 3 and IH) (6) |- E[e1'] : t (4, 5 and Lemma 1) Decomposition Lemma: If |- e: t then either (1) e is a value v or (2) e is one of the following forms: (a) e = E[e'] and e' = (\x: t. e'') v (b) e = E[e'] and e' = if true then e1 else e2 (c) e = E[e'] and e' = if false then e1 else e2 Progress: if |- e : t then e is a value v or e -> e' Proof: By decomposition, e is either a value or case 2a, 2b or 2c applies. Case 1: e = v, case proved trivially Case 2a: e = E[e'] and e' = (\x: t.e'') v By e-Context rule: (\x:t.e'') v -> e''[v/x] ----------------------------- E[(\x:t.e'') v] -> E[e''[v/x]] Therefore e -> e' Cases 2b and 2c follows similarly using Rules If-true and If-false. Adding exception to the language: e::= ... | fail | try e1 with e2 E::= ... | try E with e2 Example: try (fun mydiv (x:int) : int = if x = 0 then fail else (3/x)) 0 with 0 Typing rules: G |- e1 : t G |- e2 : t -------------------------- G |- try e1 with e2 : t --------------- (any type for fail) G |- fail : t Operational rules: E != E1[try E2 with e] ---------------------- E[fail] -> fail E!= E1[try E2 with e] -------------------------- try (E[fail]) with e -> e