(* CS:3820, Fall 2016 *) (* Cesare Tinelli *) (* The University of Iowa *) (* F# examples seen in class *) (* Algebraic data types *) (* aka Discriminated Unions *) type mood = Happy | Sad | Mad let m = Happy let f = function Happy -> "\n:-)\n" | Sad -> "\n:-(\n" | _ -> "\n:-@\n" System.Console.WriteLine (f Happy) type btree = Empty | Node of (int * btree * btree) Empty let e = Empty let t3 = Node(3,e,e) let t5 = Node(5,e,e) let t9 = Node(9,t3,t5) let t4 = Node(4,t9,e) t4 (* (4) / \ (9) () / \ / \ (3) (5) / \ / \ () () () () *) let newTree n = Node(n, Empty, Empty) // Extracts value of root node if t is a non-empty tree let rootValue t = match t with Node (v, _, _) -> v | _ -> failwith "Empty tree" rootValue t3 rootValue e // Extracts left subtree if t is non-empty let leftChild t = match t with Node (_, t, _) -> t | _ -> failwith "Empty tree" t3 leftChild t3 // Extracts right subtree if t is non-empty let rightChild t = match t with Node (_, _, t) -> t | _ -> failwith "Empty tree" // returns true iff integer n occurs in tree t let rec occurs n t = match t with Empty -> false | Node (m, t1, t2) -> (m = n) || (occurs n t1) || (occurs n t2) occurs 10 t4 occurs 9 t4 // "inserts" integer n in tree t so that // all nodes to the left have a smaller or equal value let rec insert n t = match t with Empty -> newTree n | Node (m, t1, t2) -> if (n < m) then Node (m, insert n t1, t2) else Node (m, t1, insert n t2) let s = Node (3, Empty, Node (6, Empty, Empty)) (* (3) / \ () (6) / \ () () *) let s1 = insert 4 s (* (3) / \ () (6) / \ (4) () / \ () () *) let s2 = insert 5 s1 (* (3) / \ () (6) / \ (4) () / \ () (5) / \ () () *) // collects all integer values in tree t into a list let rec traverse t = match t with Empty -> [] | Node (m,t1,t2) -> let l1 = traverse t1 in let l2 = traverse t2 in l1 @ [m] @ l2 traverse s2 (* From Chap 1 of the Sestoft *) (* Representing object language expressions using recursive datatypes *) type expr = | CstI of int | Prim of string * expr * expr let e1 = CstI 17 (* [17] *) let e2 = Prim("-", CstI 3, CstI 4) (* [-] / \ [3] [4] *) let e3 = Prim("+", Prim("*", CstI 7, CstI 9), CstI 10) (* [+] / \ [*] [10] / \ [7] [9] *) (* Evaluating expressions using recursive functions *) let rec eval (e : expr) : int = match e with | CstI i -> i | Prim("+", e1, e2) -> eval e1 + eval e2 | Prim("*", e1, e2) -> eval e1 * eval e2 | Prim("-", e1, e2) -> eval e1 - eval e2 | Prim _ -> failwith "unknown primitive" let e1v = eval e1 let e2v = eval e2 let e3v = eval e3 (* Changing the meaning of subtraction *) let rec evalm (e : expr) : int = match e with | CstI i -> i | Prim("+", e1, e2) -> evalm e1 + evalm e2 | Prim("*", e1, e2) -> evalm e1 * evalm e2 | Prim("-", e1, e2) -> let res = evalm e1 - evalm e2 in if res < 0 then 0 else res | Prim _ -> failwith "unknown primitive" let e4v = evalm (Prim("-", CstI 10, CstI 27))