Algebraic data types ==================== 1) Defining a set - datatype day = M | Tu | W | Th | F | Sa | Su; - fun isWeekend x = (x = Sa orelse x = Su); 2) Defining a /discriminated/ union in ML: datatype element = I of int | F of real; fun getReal (F x) = x | getReal (I x) = real x; (* boolean algebra *) datatype Proposition = True | Not of Proposition | And of Proposition * Proposition | Or of Proposition * Proposition val prop : Proposition = Or True (Not True) fun eval True = true | eval (Not x) = not (eval x) | eval (And (x,y)) = (eval x) andalso (eval y) | eval (Or (x,y)) = (eval x) orelse (eval y) (* binary tree *) datatype btree = Empty | Node of (btree * int * btree) Empty val e = Empty val t3 = Node(e,3,e) val t5 = Node (e, 5, e) val t9 = Node (t3,9,t5) val t4 = Node(t9,4,e) t4 (* t4 corresponds to this tree: (4) / \ (9) () / \ / \ (3) (5) / \ / \ () () () () *) fun newTree n = Node (Empty, n, Empty) newTree 10 -- Extracts value of root node if t is a non-empty tree fun rootValue (Node (_, v, _)) = v | rootValue _ = raise Match t3 rootValue t3 rootValue e -- Extracts left subtree if t is non-empty fun leftChild (Node (t, _, _)) = t | leftChild _ = raise Match t3 leftChild t3 t9 leftChild t9 -- Extracts right subtree if t is non-empty fun rightChild (Node (_, _, t)) = t | rightChild _ = raise Match -- returns true iff integer n occurs in tree t fun occurs _ (Empty) = false | occurs n (Node (t1, m, t2)) = (m = n) orelse (occurs n t1) orelse (occurs n t2) t4 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 (t1, m, t2) -> if (n < m) then Node (insert n t1, m, t2) else Node (t1, m, insert n t2) val s = Node (Empty, 3, Node (Empty, 6, Empty)) (* (3) / \ () (6) / \ () () *) val s1 = insert 4 s (* (3) / \ () (6) / \ (4) () / \ () () *) val 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 (t1, m, t2) -> let l1 = traverse t1 in let l2 = traverse t2 in l1 @ [m] @ l2 traverse s2