You did great on the midterm! It was difficult and you all pushed really hard, and I'm proud of what we did. It's clear that you guys are learning PL and that I'm learning about learning PL :) OK, so we're here to learn, so let's see how we can do that. I started skimming the tests and I talked to a few of you and I think it'd be useful to go over that predecessor problem in slow motion. [ DO #4 ON WHITEBOARD ] Whew, OK. But this is all to get subtraction? And only for positive numbers? Which are represented as functions? Nonsense! Why are we doing this to ourselves? Well, why to people run when we have bicycles and cars? We're building our PL muscles. But we've been doing the running version. You can also build muscle on a bike and make a lot more progress a lot more quickly. So let's look at extending our lambda calculus with a handful of more realistic language features. We'll actually be able to build up to something approaching OCaml (if you squint really hard) just in the time we have left in class today. One thing that we don't want to happen when we start extending our lambda calculus, is to invalidate all that hard work we did a couple lectures back to prove that our type systems was good: i.e. the type safety proof. What did that say again? Oh yes: "Well typed terms do not get stuck." or, more formally: If * |- e : T and e -*-> e', then either e' is a value of there exists e'' such that e' -> e''. And how did we prove it? With Progress and Preservation: Progress: If * |- e : T, then either (1) e is a value or (2) there exists e' such that e -> e'. Preservation: If * |- e : T and e -> e', then * |- e' : T. At a high level Progress works by: induction on * |- e : T base cases either: (A) either value (done) (B) not typable in empty context (contradiction, done) inductive cases: - inversion on typing judgement to get types for subexpressions - IH + subexpression types gives that they are values or can step - if subexpression steps, big expression steps - NOTE: use canonical forms lemma to get shape of well typed values At a high level Preservation works by: induction on * |- e : T base cases all contradictions, either (A) not typable in empty context (bogus) (B) cannot step (bogus) inductive cases: - inversion on typing judgement to get types for subexpressions - case analysis on step + inversion to get subexpression step - IH + subexp type + subexp step gives subexp still well typed - stitch back together to show big expr still well typed - NOTE: use substitution lemma to handle call case of app So, when we extend lambda calculus we want to make sure these things still hold. In general there are few things we'll need to provide for each extension: - syntax for new construct - semantics for new construct - types for new construct - patch to progress to handle this case - patch to preservation to handle this case - ... details we'll ignore (extend canonical forms, extend substitution) OK, let's start extending our language! We'll do lets, the easy one, first all together on the board, then you'll split in to small groups of 4 to do booleans, pairs, and sums.