Include sample output! You don't have to write special test routines, but you should include as a comment in your file at least two calls to each function you are asked to write. See the file sample.ml in ~schar/cs313/ml/ for an example. Be creative - use your own test cases rather than the ones shown below.
Upload your file via the HW 8 submission page by the beginning of class on Wednesday.
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:~% rlwrap sml Standard ML of New Jersey v110.80 [built: Mon Feb 6 17:36:11 2017] -
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:
Implement the following functions:(* type definition *) datatype bst = Empty | Node of int * bst * bst; (* useful function to create a leaf node *) fun leaf n = Node(n, Empty, Empty);
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
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".- 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
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