At the prompt you can enter ML expressions, terminated by a semicolon. If your expression extends over several lines, the prompt "-" will change to "=".abe:~% sml Standard ML of New Jersey v110.69 [built: Thu Mar 19 14:05:38 2009] -
You can load a file with the command "use":- val x = 3; val x = 3 : int - fun length [] = 0 = | length (a::y) = 1 + length y; val length = fn : 'a list -> int - length [2, 4, 6, 8]; val it = 4 : int
To exit, type control-D.- use "sample.ml"; [opening sample.ml] val sumlist1 = fn : int list -> int GC #0.0.0.0.1.12: (10 ms) val sumlist2 = fn : int list -> int val sumlist3 = fn : int list -> int val sumlist4 = fn : int list -> int datatype bst = Empty | Node of int * bst * bst val leaf = fn : int -> bst val height = fn : bst -> int val it = () : unit -
- fromToBy(10, 20, 1); val it = [10,11,12,13,14,15,16,17,18,19,20] : int list - fromToBy(1, 20, 3); val it = [1,4,7,10,13,16,19] : int list
- fact 7; val it = 5040 : int - map fact (fromToBy(0, 6, 1)); val it = [1,1,2,6,24,120,720] : int list - fib 7; val it = 13 : int - map fib (fromToBy(0, 10, 1)); val it = [0,1,1,2,3,5,8,13,21,34,55] : int list
Sample output:
- mapcons(3, [[2], [4, 5], [], [6, 6, 6]]); val it = [[3,2],[3,4,5],[3],[3,6,6,6]] : int list list - subsets []; stdIn:35.1-35.11 Warning: type vars not generalized because of value restriction are instantiated to dummy types (X1,X2,...) val it = [[]] : ?.X1 list list - subsets ([] : int list); val it = [[]] : int list list - subsets [1]; val it = [[1],[]] : int list list - subsets ["a", "b"]; val it = [["a","b"],["a"],["b"],[]] : string list list - subsets [1, 2, 3]; val it = [[1,2,3],[1,2],[1,3],[1],[2,3],[2],[3],[]] : int list list
a perfect shuffle yields[1, 2, 3, 4, 5, 6, 7, 8],
A second perfect shuffle yields[1, 5, 2, 6, 3, 7, 4, 8].
and a third perfect shuffle restores the original order:[1, 3, 5, 7, 2, 4, 6, 8],
Therefore, the shuffle period of 8 is 3.[1, 2, 3, 4, 5, 6, 7, 8].
Implement the following functions:
an inverse perfect shuffle yields[1, 2, 3, 4, 5, 6, 7, 8]
For this problem, you can implement either of the two operations.[1, 3, 5, 7, 2, 4, 6, 8].
Sample output:
- idlist 6; val it = [1,2,3,4,5,6] : int list - shuffle(idlist 6); (* regular shuffle *) val it = [1,4,2,5,3,6] : int list - shuffle2(idlist 6); (* inverse shuffle *) val it = [1,3,5,2,4,6] : int list - shuffleperiod 8; val it = 3 : int - map shuffleperiod (fromToBy(2, 20, 2)); val it = [1,2,4,3,6,10,12,4,8,18] : int list
The goal of this last problem is to implement general (polymorphic) BSTs that can hold values of any type and support user-defined comparison operations. I advise you, however, to proceed in two steps as outlined below, and start by implementing the good old integer BSTs. You only need to hand in code and sample output of your final code, but you should save a backup copy of your working code for step 1 in a comment before moving on! (ML's comments, handily, can be nested.)
Step 1: Use the datatype definition from the file sample.ml:
(* type definition *)
datatype bst = Empty
| Node of int * bst * bst;
(* useful function to create a leaf node *)
fun leaf n = Node(n, Empty, Empty);
Implement the following functions:
Sample output:
Step 2: First, generalize your datatype definition to handle arbitrary types. Sample output after this change:- val t = Node(3, Node(1, Empty, leaf(2)), leaf(4)); val t = Node (3,Node (1,Empty,Node #),Node (4,Empty,Empty)) : bst - map (fn x => member(x, t)) [0, 3, 5]; val it = [false,true,false] : bool list - insert(5, leaf(2)); val it = Node (2,Empty,Node (5,Empty,Empty)) : bst - insertList [2, 5]; val it = Node (5,Node (2,Empty,Empty),Empty) : bst - inOrder(t); val it = [1,2,3,4] : int list - treeSort [3, 2, 6, 4, 1, 4, 5]; val it = [1,2,3,4,4,5,6] : int list
- leaf("abc");
val it = Node ("abc",Empty,Empty) : string bst
- Node(3.5, leaf(0.3), Empty);
val it = Node (3.5,Node (0.3,Empty,Empty),Empty) : real bst
After you have made this change you will notice that ML still thinks
that functions insert, member, etc. operate on an int bst rather
than the desired 'a bst. The reason is that these functions use
comparisons like "<", whose types default to "int * int ->
bool".
For full generality, the comparison function needs to be passed to member, insert, insertList, and treeSort as an extra parameter. Rewrite these functions appropriately. Sample output (note that "op <" turns the infix operator "<" into a function):
- insert("b", leaf("a"), op <);
val it = Node ("a",Empty,Node ("b",Empty,Empty)) : string bst
- val t = insertList([0.6, ~1.0, 0.2], op <);
val t = Node (0.2,Node (~1.0,Empty,Empty),Node (0.6,Empty,Empty)) : real bst
- member(0.6, t, op <);
val it = true : bool
- treeSort([2,3,6,~2,~5,0,7,3,~2], op <);
val it = [~5,~2,~2,0,2,3,3,6,7] : int list
- treeSort([2,3,6,~2,~5,0,7,3,~2], op >);
val it = [7,6,3,3,2,0,~2,~2,~5] : int list
- treeSort([2,3,6,~2,~5,0,7,3,~2], fn(a, b) => abs a < abs b);
val it = [0,2,~2,~2,3,3,~5,6,7] : int list