1. The problem of uninhabited types. What happens if a type has no values? Comparison to type with exactly one value. Bottom type. Void type. Say we have an expression e with type t. "Inhabitation". - When we evaluate expression e, the interpreter will not "get stuck", and _when_ it terminates, it produces a value v of type t. - "Bottom type" uninhabited. The only value an expresion can have bottom type is if it never returns. - Useful, for example in loops. Infinite loops. Main loop. Servers, daemons, operating systems, ... - Just because an expression e has a type t, and there is some value v with type t, does not mean that evaluating e will terminate. - If an expression e has type t, and there are no values of of type t, then e _cannot_ terminate. - int "->" int : The type of functions, arrows. - Implications. "If a then b": "a => b". - Curry Howard Isomorphism. "Types in functional programs are the _____same______ as propositions in logic." - The type with no inhabitants is the proposition "False". - Do not compare void to the unininhabited type. If you are insistent, the unit type is a better analogy. 2. Let expressions: let x = 5 in (let x = 3 in x) + x - Scope hierarchies. - Brackets: let x = 5 in (let x = 3 in x) + x (let x = 5 in ((let x = 3 in x) + x)) (let x = (e1) in (e2)) - Proposal 1 - Evaluate e1. Say the value is v1. - Look inside e2. Replace every occurrence of the variable x with v1 unless it is overwritten by nested let expression. - Evaluate the result of the substitution e2{ v1 / x }. - Proposal 2 - Evaluate e1. Say the value is v1. - Look inside e2. Replace every occurrence of the variable x with v1 unless it is overwritten by nested let expression and it was ____shadowed____. - Evaluate the result of the substitution e2{ v1 / x }. let x = 5 in (let x = 3 in x) + x - Evaluate 5. - Look inside e2 = (let x = 3 in x) + x. Replace every occurrence of x with 5. - Suggestion 1: e2{ 5 / x } = (let 5 = 3 in 5) + 5. - let x = 5 in (x) + x;; - let x = 5 in (let y = 3 in x) + x;; - Prediction 1. Error: unused / unbound variable y undefined variable x - Prediction 2. No error. 10. - 3 + 4 + 5. Is this 3 + 9 = 12, or is this 7 + 5 = 12? - 3 - 4 + 5. Is this 3 - 9 = -6, or is this -1 + 5 = 4? - Always good practice to explicitly disambiguate: (3 - 4) + 5 or 3 - (4 + 5);; - Completely parenthesized let expression: (let x = (e1) in (e2)) - Evaluate e1. Say it produces value v1. - Substitute v1 for x in e2, modulo shadowing. - Evaluate e2 { v1 / x }. - let x = 5 in (let x = (x + x) in x) + x;; - Evaluate e1 = 5. This is 5, duh! - Substitute 5 wherever I see x in e2 = (let x = (x + x) in x) + x e2 { 5 / x } = (let x = (5 + 5) in x) + 5 - Evaluate (let x = (5 + 5) in x) + 5 - Evaluate e1 = 5 + 5. 10, duh! - Replace 10 wherever I see x in e2, modulo shadowing. e2 = x. Shadowing plays no role. e2 { 10 / x} = 10. - We're left with 10 + 5. - This is 15. - Is shadowing the same as mutation? int x, y; x = 5; if (true) { x = 3; y = x + x; } x = x + y; // x = 9; let x = 5 in (let x = 3 in x + x) + x Shadowing is not mutation. You can get shadowing in C with functions. Stack frames. int y; int x = 5; if (true) { int x = 3; y = x + x; } x = x + y; // x = 11 - Components of the mental model: How to evaluate function applications, let expressions, pattern matches, closures. - Aside: Boolean and and or && and || are "short-circuited". - When we see a function application (ef e1 e2 e3 ... ek). In a C-like language, ef(e1, e2, ..., ek). - Evaluate ef, e1, e2, .... ek. in no specific order. - The typechecker guarantees that ef will evaluate to a function expression. - apply that function to the k results, v1, v2, ... vk. - let add m n = m + n;; - add (add 2 3) (add (add 3 6) (add 2 8)) ==> add (add 2 3) (add (add 3 6) 10) ==> add (add 2 3) (add 9 10) ==> add (add 2 3) 19 ==> add 5 19 ==> 24 - int add(int m, int n); - add(add(2, 3), add(add(3, 6), add(2, 8))) ==> add(add(2, 3), add(9, add(2, 8))) ==> add(add(2, 3), add(9, 10)) ==> add(5, add(9, 10)) ==> add(5, 19) ==> 24. - In C: - When I see a function application, 1. Recursively evaluate arguments, in any order I please. 2. Apply the function to the arguments. - C does not specify order of evaluation of function arguments. Undefined behaviors. - let exp n = fun x -> x ** n - (exp 3.) 2. ==> (fun x -> x ** 3.) 2. ==> 2. ** 3. ==> 8 fun = lambda! - Records. Homework: Chapters 5 and 6 of RWO. - Variants and algebraic data types. - Constructors. - ____ Destructors. ____ - Pattern matching.