Programming Languages---Course 66.443
``Utopia 84'' comes from a prediction made D. Knuth in 1974.
raju.cs.rpi.edu% sml Standard ML of New Jersey, Version 75, November 11, 1991 Arrays have changed; see Release Notes val it = () : unit - odd(3); std_in:2.1-2.3 Error: unbound variable or constructor odd - 7 mod 2; val it = 1 : int - ~7 mod 2; val it = 1 : int - ~7 rem 2; val it = ~1 : int - fun odd(n) = (n mod 2 = 1); val odd = fn : int -> bool - odd(3); val it = true : bool - (* iota(n) returns the list [0,1,2,...,n-1] *) - fun iota(n) = if n = 0 then nil else iota(n-1) @ [n-1]; val iota = fn : int -> int list - iota(12); val it = [0,1,2,3,4,5,6,7,8,9,10,11] : int list - rev(it); val it = [11,10,9,8,7,6,5,4,3,2,1,0] : int list - (* another (algorithmicly better) way to define iota *) - fun reverse'iota(n) = if n=0 then nil else (n-1)::reverse'iota(n-1); val reverse'iota = fn : int -> int list - reverse'iota(8); val it = [7,6,5,4,3,2,1,0] : int list - fun iota(n) = rev(reverse'iota(n)); val iota = fn : int -> int list - iota(10); val it = [0,1,2,3,4,5,6,7,8,9] : int list - odd(hd(it)); val it = false : bool - val l1 = iota(10); val l1 = [0,1,2,3,4,5,6,7,8,9] : int list - odd(hd(l1)); val it = false : bool - tl(l1); val it = [1,2,3,4,5,6,7,8,9] : int list - odd(hd(it)); val it = true : bool - (* count(l, p) returns the number of elements of list l that make - predicate p true *) - fun count(l, p) = if null(l) then 0 else = count(tl(l),p) + (if p(hd(l)) then 1 else 0); val count = fn : 'a list * ('a -> bool) -> int - count(l1,odd); val it = 5 : int - count(l1,true); std_in:20.1-20.14 Error: operator and operand don't agree (tycon mismatch) operator domain: int list * (int -> bool) operand: int list * bool in expression: count (l1,true) - fun always(n) = true; val always = fn : 'a -> bool - count(l1,always); (* count(l,always) = length(l) *) val it = 10 : int - count(tl(l1),odd); val it = 5 : int - count(tl(tl(l1)),odd); val it = 4 : int - (* functions on lists can be defined using pattern-matching *) - fun count(nil,p) = 0 = | count(x::xs,p) = count(xs,p) + (if p(x) then 1 else 0); val count = fn : 'a list * ('a -> bool) -> int - count(l1,odd); val it = 5 : int - (* select returns the list of elements that satisfy a predicate p *) - fun select(nil,p) = nil = | select(x::xs,p) = if p(x) then x::select(xs,p) else select(xs,p); val select = fn : 'a list * ('a -> bool) -> 'a list - select(l1,odd); val it = [1,3,5,7,9] : int list - fun even(n) = ~odd(n); std_in:6.15 Error: overloaded variable "~" not defined at type: int -> bool - fun even(n) = not(odd(n)); val even = fn : int -> bool - select(l1,even); val it = [0,2,4,6,8] : int list - (* it's possible to construct and pass an "anonymous function" *) - select(l1, fn(n) => n mod 2 = 1); (* same as select(l1,odd) *) [Major collection... [Increasing heap to 2076k] 26% used (428368/1645032), 560 msec] [Increasing heap to 2160k] val it = [1,3,5,7,9] : int list - (* map f [x1,x2,...,xn] returns [f(x1),f(x2),...,f(xn)] *) - fun square(n) = n*n; std_in:10.19 Error: overloaded variable "*" cannot be resolved - (* we must give ML some type information in this case *) - fun square(n:int) = n*n; val square = fn : int -> int - val l4 = map square l1; val l4 = [0,1,4,9,16,25,36,49,64,81] : int list - select(l4,odd); val it = [1,9,25,49,81] : int list - val ms = map square; val ms = fn : int list -> int list - ms l1; val it = [0,1,4,9,16,25,36,49,64,81] : int list - ms (ms l1); val it = [0,1,16,81,256,625,1296,2401,4096,6561] : int list (* reduce combines the elements of a list using a 2-argument function F *) - exception EmptyList; exception EmptyList - fun reduce(F,nil) = raise EmptyList = | reduce(F,[a]) = a = | reduce(F,x::xs) = F(x,reduce(F,xs)); val reduce = fn : ('a * 'a -> 'a) * 'a list -> 'a - reduce(op +, l1); val it = 45 : int - reduce(op *, l1); val it = 0 : int - reduce(op *, tl l1); val it = 362880 : int - fun fact(n) = reduce(op *, tl(iota(n+1))); val fact = fn : int -> int - fact(9); val it = 362880 : int - fact(5); val it = 120 : int val sl = ["Now"," is"," the"," time..."] : string list - reduce(op ^, sl); val it = "Now is the time..." : string - (* It's possible to define new types; here's a very simple case *) - datatype color = Red | Green | Blue; datatype color con Blue : color con Green : color con Red : color - fun isRed(c) = (c=Red); val isRed = fn : color -> bool - isRed(Red); val it = true : bool - isRed(Blue); val it = false : bool - isRed(5); std_in:8.1-8.8 Error: operator and operand don't agree (tycon mismatch) operator domain: color operand: int in expression: isRed (5) (* Recursive type: labelled binary tree *) - datatype 'label btree = = Empty = | Node of 'label * 'label btree * 'label btree; datatype 'a btree con Empty : 'a btree con Node : 'a * 'a btree * 'a btree -> 'a btree - Node("abc",Empty,Empty); val it = Node ("abc",Empty,Empty) : string btree - val t1 = Node("xyz",it,it); val t1 = Node ("xyz",Node ("abc",Empty,Empty),Node ("abc",Empty,Empty)) : string btree - val t2 = Node("foo",Empty,t1); val t2 = Node ("foo",Empty,Node ("xyz",Node #,Node #)) : string btree - fun lookup(x, Empty) = false = | lookup(x, Node(y,left,right)) = = if x=y then true = else if x < y then lookup(x,left) = else lookup(x,right); std_in:4.18 Error: overloaded variable "<" cannot be resolved - fun lookup(x, Empty) = false | lookup(x, Node(y,left,right)) = if x=y then true else if (x:string) < y then lookup(x,left) else (* x > y *) lookup(x,right); = = = = val lookup = fn : string * string btree -> bool - lookup("xyz",t2); val it = true : bool - lookup("foo",t2); val it = true : bool - lookup("bar",t2); val it = false : bool - fun sum(Empty) = 0 = | sum(Node(a,left,right)) = a + sum(left) + sum(right); val sum = fn : int btree -> int - fun cat(Empty) = "" = | cat(Node(a,left,right)) = a ^ cat(left) ^ cat(right); val cat = fn : string btree -> string - t2; val it = Node ("foo",Empty,Node ("xyz",Node #,Node #)) : string btree - cat(t2); val it = "fooxyzabcabc" : string - fun insert(x,Empty) = Node(x,Empty,Empty) = | insert(x,T as Node(y,left,right)) = = if x=y then T = else if (x:string)<y then Node(y,insert(x,left),right) = else Node(y,left,insert(x,right)); val insert = fn : string * string btree -> string btree - val t3 = insert("now",insert("is",insert("the",insert("time",Empty)))); val t3 = Node ("time",Node ("the",Node #,Empty),Empty) : string btree - insert("for",t3); val it = Node ("time",Node ("the",Node #,Empty),Empty) : string btree - cat(it); val it = "timetheisfornow" : string - (* Here's an abstract data type definition---"abstract" because - it hides the representation. We read it from a file "bst.ml" *) - use "bst.ml"; [opening bst.ml] structure StringBST : sig datatype 'a btree con Empty : 'a btree con Node : 'a * 'a btree * 'a btree -> 'a btree val create : 'a btree val insert : string * string btree -> string btree val lookup : string * string btree -> bool end [closing bst.ml] val it = () : unit - ^D
structure StringBST = struct datatype 'label btree = Empty | Node of 'label * 'label btree * 'label btree; val create = Empty; fun insert(x,Empty) = Node(x,Empty,Empty) | insert(x,T as Node(y,left,right)) = if x=y then T else if (x:string) < y then Node(y,insert(x,left),right) else Node(y,left,insert(x,right)); fun lookup(x, Empty) = false | lookup(x, Node(y,left,right)) = if x=y then true else if (x:string) < y then lookup(x,left) else lookup(x,right); end;