News CSE 130: Spring 2012 Programming Languages On webpage: Suggested HW #1 PA #1 (due next Fri 4/13) Lecture 2: A Crash Course in ML Please post questions to Piazza Ranjit Jhala UC San Diego Today: A crash course in ML contd 1 2 Recap: ML s Holy Trinity Complex types: Lists essions (Syntax) Exec-time Dynamic Values (Semantics) []; [] a list [1;2;3]; [1;2;3] int list [1+1;2+2;3+3;4+4]; [2;4;6;8] int list Compile-time Static Types [ a ; b ; c ^ d ]; [ a ; b ; cd ] string list [(1, a ^ b );(3+4, c )]; [(1, ab );(7, c )] (int*string) list 1. Programmer enters expression 2. ML checks if expression is well-typed Using a precise set of rules, ML tries to find a unique type for the expression meaningful type for the expr 3. ML evaluates expression to compute value Of the same type found in step 2 [[1];[2;3];[4;5;6]]; [[1];[2;3];[4;5;6]]; (int list) list Unbounded size Can have lists of anything (e.g. lists of lists) But 3 4
Complex types: Lists Complex types: Lists List operator Cons :: [1; pq ]; All elements must have same type 1::[]; [1] int list 1::[2;3]; [1;2;3] int list a ::[ b ; c ]; [ a ; b ; c ] string list Can only cons element to a list of same type 1::[ b ; cd ]; 5 6 Lists: Construct Complex types: Lists Nil operator List operator Append @ [] []: a list [] => [] [1;2]@[3;4;5]; [1;2;3;4;5] int list [ a ]@[ b ]; [ a ; b ] string list []@[1]; [1] int list Cons operator 1::[2;3] [1;2;3] int list Can only append two lists 1 @ [2;3]; e1:t e2: T list e1=>v1 e2=> v2 of the same type [1] @ [ a ; b ]; e1::e2 : T list e1::e2 => v1::v2 7 8
Complex types: Lists Complex types: Lists List operator head hd List operator tail tl hd [1;2]; 1 int tl [1;2;3]; [2;3] int list hd ([ a ]@[ b ]); a string tl ([ a ]@[ b ]); [ b ] string list Only take the head a nonempty list hd []; Only take the tail of nonempty list tl []; 9 10 Lists: Deconstruct Recap: Tuples vs. Lists? e :T list e => v1::v2 Head hd e : T hd e => v1 Tail e :T list e => v1::v2 tl e : T list tl e => v2 (hd [[];[1;2;3]]) = (hd [[];[ a ]]) int list e string list 1 :T e 2 :T What s the difference? Tuples: Different types, but fixed number: (3, abcd ) (int * string) pair = 2 elts (3, abcd,(3.5,4.2)) (int * string * (float * float)) triple = 3 elts Lists: Same type, unbounded number: [3;4;5;6;7] int list e 1 =e 2 : bool 11 12
So far, a fancy calculator So far, a fancy calculator what do we need next? Branches 13 14 If-then-else expressions If-then-else expressions e1 : bool e2: T e3: T if (1 < 2) then [1;2] else 5 if e1 then e2 else e3 : T if false then [1;2] else 5 Then-subexp, Else-subexp must have same type! Equals type of resulting expression then-subexp, else-subexp must have same type! which is the type of resulting expression if 1>2 then [1,2] else [] [] if 1<2 then [] else [ a ] [] int list string list (if 1>2 then [1,2] else [])=(if 1<2 then [] else [ a ]) e1 : bool e2: T e3: T if e1 then e2 else e3 : T 15 16
So far, a fancy calculator Variables and bindings let x = e; Variables Bind the value of expression e to the variable x # let x = 2+2;; val x : int = 4 17 18 Variables and bindings Variables and bindings Later declared expressions can use x Most recent bound value used for evaluation # let x = 2+2;; val x : int = 4 # let y = x * x * x;; val y : int = 64 # let z = [x;y;x+y];; val z : int list = [4;64;68] # Undeclared variables (i.e. without a value binding) are not accepted! # let p = a + 1; Characters 8-9: let p = a + 1 ;; ^ Unbound value a Catches many bugs due to typos 19 20
Local bindings Binding by Pattern-Matching for expressions using temporary variables let tempvar = x + 2 * y in tempvar * tempvar ;; 17424 int Simultaneously bind several variables # let (x,y,z) = (2+3, a ^ b, 1::[2]);; val x : int = 5 tempvar is bound only inside expr body from in Not visible ( not in scope ) outside val y : string = ab val z : int list = [1;2] 21 22 Binding by Pattern-Matching But what of: # let h::t = [1;2;3];; Warning P: this pattern-matching not exhaustive. val h : int = 1 val t : int list = [2;3] Why is it whining? # let h::t = []; Exception: Match_failure # let XS = [1;2;3]; val xs = [1;2;3]: list - val h::t = xs; Warning: Binding not exhaustive val h = 1 : int val t = [2;3] : int In general xs may be empty (match failure!) Another useful early warning 23 Functions 24
Next class: functions, but remember ession Value Type Complex types: Functions! fun x -> x+1;; int -> int Everything is an expression Everything has a value Everything has a type A function is a value! # let inc = fun x -> x+1 ; val inc : int -> int = # inc 0; val it : int = 1 # inc 10; val it : int = 11 25 26 A Problem A Solution: Simultaneous Binding fun x -> x+1;; fun (x,y) -> x<y; int -> int (int * int) -> bool Functions only have ONE parameter?! How a call ( application ) is evaluated: 1. Evaluate argument 2. Bind formal to arg value 3. Evaluate expr Functions only have ONE parameter? How a call ( application ) is evaluated: 1. Evaluate argument 2. Bind formal to arg value 3. Evaluate expr 27 28
Another Solution ( Currying ) And how about fun x -> fun y-> x<y; fun f -> fun x -> not(f x); int -> (int -> bool) ( a ->bool) -> ( a -> bool) Whoa! A function can return a function A function can also take a function argument # let lt = fun x -> fun y -> x < y ; val lt : int -> int -> bool = # let is5lt = lt 5; val is5lt : int -> bool = ; # is5lt 10; # is5lt 2; 29 # let neg = fun f -> fun x -> not (f x); val lt : int -> int -> bool = # let is5gte = neg is5lt; val is5gte : int -> bool = # is5gte 10; # is5gte 2; (* odd, even *) 30 A shorthand for function binding Put it together: a filter function # let neg = fun f -> fun x -> not (f x); # let neg f x = not (f x); val neg : int -> int -> bool = # let is5gte = neg is5lt; val is5gte : int -> bool = ; # is5gte 10; # is5gte 2; If arg matches this pattern then use this - let rec filter f xs = match xs with [] -> [] (x::xs )-> if f x then x::(filter f xs ) else (filter f xs );; val filter : ( a->bool)-> a list-> a lisi) = # let list1 = [1;31;12;4;7;2;10];; # filter is5lt list1 ;; val it : int list = [31;12;7;10] # filter is5gte list1;; val it : int list = [1;4;2] # filter even list1;; val it : int list = [12;4;2;10] 31 32
Put it together: a partition function A little trick # 2 <= 3;; val it : bool = true # ba <= ab ;; val it : bool = false # let partition f l = (filter f l, filter (neg f) l); val partition :( a->bool)-> a list-> a lisi * a list = # let list1 = [1,31,12,4,7,2,10]; - # partition is5lt list1 ; val it : (int list * int list) = ([31,12,7,10],[1,2,10] # partition even list1; val it : (int list * int list) = ([12,4,2,10],[1,31,7]) # let lt = (<) ;; val it : a -> a -> bool = # lt 2 3;; # lt ba ab ;; # let is5lt = lt 5; val is5lt : int -> bool = ; # is5lt 10; # is5lt 2; 33 34 Put it together: a quicksort function let rec sort xs = match xs with [] -> [] (h::t) -> let (l,r) = partition ((<) h) t in (sort l)@(h::(sort r)) Now, lets begin at the beginning 35