CS 541 Lecture -*- Outline -*- * concrete-data (Ch 4 in "ML for the working programmer") ad: variant (or disjoint union types) and generalized recursion schemes will also be useful in writing semantics to represent abstract syntax. ** datatype declarations (page 104ff) *** enumeration (section 4.2) ---------------- DATATYPE DECLARATIONS SIMULATING ENUMERATIONS - datatype color = red | blue | yellow; datatype color con blue : color con red : color con yellow : color - blue; val it = blue : color ---------------- Q: how would you define bool as a datatype? *** tagged, discriminated union (section 4.1) like oneofs in CLU, variant records in Pascal or Ada, akin to unions in C, these are more secure than Pascal and C. -------------- TAGGED, DISCRIMINATED UNIONS - datatype Expression = varExpr of string | intLiteral of int | boolLiteral of bool | andExpr of Expression * Expression | plusExpr of Expression * Expression; datatype Expression con andExpr : Expression * Expression -> Expression con boolLiteral : bool -> Expression con intLiteral : int -> Expression con plusExpr : Expression * Expression -> Expression con varExpr : string -> Expression -------------- The output shows that we have defined various constructor functions. These are like regular functions (have a function type), but can also be used in pattern matching. --------------- - boolLiteral; val it = fn : bool -> Expression - boolLiteral(true); val it = boolLiteral true : Expression - val boolLiteral(b) = it; std_in:... Warning: binding not exhaustive boolLiteral b = ... val b = true : bool ------------------ Q: what is a datatype declaration like? it's like a grammar! Q: what are these injection functions like? Useful analogy: like taking an envelope, putting the arguement in it, writing the tag on the outside Draw picture. ----------------- A SMALL EVALUATOR datatype Value = truthValue of bool | integer of int; datatype Bindable = value of Value | error; type Environ = string -> Bindable; fun eval (varExpr(v)) (u:Environ) = u(v) | eval (intLiteral(i)) u = value(integer(i)) | eval (boolLiteral(b)) u = (* fill in *) | eval (andExpr(e1,e2)) u = (case (eval e1 u, eval e2 u) of (value(truthValue(b1)), value(truthValue(b2))) => value(truthValue(b1 andalso b2)) | (x,y) => error) | eval (* fill in *) ------------------- note the parentheses are needed around intLiteral(i) this is an adequate definition, because it matches the structure of the definition of the type Expression. *** polymorphic datatypes (section 4.3, and page 119ff) **** lists -------------- POLYMORPHIC DATATYPES - datatype 'a LIST = NIL | cons of 'a * 'a LIST; datatype 'a LIST con cons : 'a * 'a LIST -> 'a LIST con NIL : 'a LIST - NIL; val it = NIL : 'a LIST - cons(3,NIL); val it = cons (3,NIL) : int LIST ---------------- Q: can you write a function length: 'a LIST -> int? **** trees ------------------- TREES datatype 'a tree = Lf | Br of 'a * 'a tree * 'a tree; fun mkLeaf x = Br(x,Lf,Lf); mkLeaf(3); val tree2 = Br(2,mkLeaf(1),mkLeaf(3)); val tree5 = Br(5,mkLeaf(6),mkLeaf(7)); val tree4 = Br(4, tree2, tree5); ------------------ Q: what is the value of tree2? of tree5? of tree4? natural recursion over trees: base case: leaf inductive case: branch -------------- fun preorder Lf = [] | preorder (Br(v,t1,t2)) = [v] @ preorder t1 @ preorder t2; fun inorder Lf = [] | inorder (Br(v,t1,t2)) = inorder t1 @ [v] @ inorder t2; -------------- note the parentheses are needed around Br(v,t1,t2) Q: can you write size: 'a tree -> int ? Q: can you write depth: 'a tree -> int ? Q: can you write sum: int tree -> int ? **** heterogeneous vectors (can omit if short on time) --------------------------- "HETEROGENEOUS" VECTORS datatype 'a vector = I of int | R of real | S of 'a | ICons of int * 'a vector | RCons of real * 'a vector | SCons of 'a * 'a vector; --------------------------- Q: What is the type of I(3)? S("hi")? S(3)? ICons(3, I(4))? Q: What is the type of ICons(3, S("hi"))? Q: how would you write square: 'a vector -> 'a vector which squares each number in a vector? ** summary datatype constructor can define recursive tree structures (expressions, etc.) each datatype comes with an induction principle (base cases, inductive cases) Q: Can you generalize these examples?