(* Meeting 10: SML: Datatypes, Type Inference, and Polymorphism *) exception Unimplemented; (*******************************************************************) (* REVIEW *) (* Lists *) []; [3]; nil; 3 :: []; nil; (op ::); (* val len : 'a list -> int Returns the length of a list. *) fun len l = if (l = nil) then 0 else 1 + len (tl l) fun len nil = 0 | len (_ :: t) = 1 + len t (* EXERCISE: Some more tail recursion practice. Write len tail recursively. *) fun len l = let (* fun len' (l, acc: int) : int = if not (l = nil) then len' (tl l, acc + 1) else acc *) fun len' (nil, acc) = acc | len' (_::t, acc) = len' (t, acc + 1) in len' (l, 0) end (* EXERCISE: Write a function that appends two lists. *) fun append (nil, l) = l | append (h :: t, l) = h :: append (t, l) (* Reverse *) fun rev nil = nil | rev (h :: t) = append (rev t, [h]) fun rev nil = nil | rev (h :: t) = rev t @ [h] (* using built-in append function *) (* EXERCISE: Write a tail recursive list reverse function. *) fun rev (l: int list) = let fun helper (nil: int list, acc: int list) : int list = acc | helper (h :: t: int list, acc: int list) : int list = helper (t, h :: acc) in helper (l, []) end (*******************************************************************) (* Datatypes *) (* Enumerations *) datatype mybool = True | False fun mynot True = False (* pattern match *) | mynot False = True (* Parameterized by types *) datatype 'a option = NONE | SOME of 'a (* Is a built-in type. *) (* What are some possible uses? *) fun reciprocal 0 = NONE | reciprocal (n: int) = SOME (1 div n) fun plusopts (NONE, _) = NONE | plusopts (_, NONE) = NONE | plusopts (SOME x, SOME y) = SOME (x + y) (* Recursive datatypes *) datatype myintlist = Nil | Cons of int * myintlist; Nil; Cons; Cons (3, Cons (4, Nil)); datatype 'a mylist = Nil | Cons of 'a * 'a mylist; Nil; Cons; type mynewintlist = int mylist; Cons (3, Cons (4, Nil)) : mynewintlist; (* EXERCISE: Define a binary tree datatype that is either empty or node with some data of type 'a and two subtrees. Then, define a function height : 'a tree -> int that returns the height of the tree. Int.max : int * int -> int returns the max of two integer values. *) datatype 'b tree = Empty | Node of 'b * 'b tree * 'b tree fun height (Empty) : int = 0 | height (Node (_, l, r)) : int = let val hl = height l val hr = height r in 1 + Int.max (hl, hr) end (* In dynamically-typed languages, we have the ability create hetereogenous data structures, like [3, "abc", 4, "def"] In SML, we can create such structures as well. How? *) datatype int_or_string = Int of int | String of string (* Abstract Syntax *) (* One of the main benefits of using a language like SML is that it is easy to work with abstract syntax. *) (* Our favorite arithmetic expression language translates directly into a datatype. e ::= n | e + e | e * e *) datatype expr = Num of int | Plus of (expr * expr) | Times of (expr * expr) (* EXERCISE: Write an evaluation function for this language. eval : expr -> int *) fun eval (Num n) = n | eval (Plus (e1, e2)) = (eval e1) + (eval e2) | eval (Times (e1, e2)) = (eval e1) * (eval e2) (*******************************************************************) (* Parametric Polymorphism *) (* We already saw datatypes that are parametric in another type (e.g., the built-in lists). Same thing applies to functions. *) (* The identity function should work on any type. *) fun id (x: int) : int = x fun id (x: real) : real = x fun id (x: string) : string = x fun id (x: 'a) : 'a = x (* 'a is called a type variable and 'a -> 'a is called a type scheme *) fun id x = x val id = (fn x => x) (* Type inference gives us the most general (i.e., least restrictive) type. The ability to do this called principal typing. *) (* What are principal types of the following functions? *) fun f (x, y, z) = y fun g (h :: t) = h (* A pecularity *) val weird = id id (* Value restriction: val declarations may be inferred to have polymorphic type only if the right-hand side is a value. *) (* Necessary for soundness of the type system in the presence of side-effects (e.g., references). *) (*******************************************************************)