How to write BST search function in Standard ML? - sml

What is required is to write a function searchBST of type ''a tree -> (''a * ''a -> bool) -> ''a -> bool
that searches a nst for a given data element. using:
datatype 'data tree = Empty
| Node of 'data tree * 'data * 'data tree
Also, we cannot search every node in the tree, but only those nodes that, according to the definition, might contain the element we are looking for.
The function that I wrote is of type (int * int tree -> bool) and I would appreciate any tips on converting it to the required type
datatype 'data tree = Empty
| Node of 'data tree * 'data * 'data tree;
fun searchBST (x, Empty) = false
| searchBST (x, Node(l, parent, r)) =
if x = parent then true
else
if x< parent then searchBST(x, l)
else searchBST(x,r)

When something has type ''a * ''a -> bool, then it is always (99,9% of the times) a predicate function. This is strongly hinted by the fact that the argument tuple ''a * ''a is an equality type (hence the douple mark, and not a single mark as "normal").
Since you are constructing a search function, your predicate function are most likely the one that should be used to define which element you are searching for.
However it could also have been the case that it defines if the desired element is in the left or right part of the tree. Though normally it would then have been a ordering function with the type ''a * ''a -> order. Such an ordering function would in any practical cases have been better, because you would then be able to abstract the ordering of element (which include equality) instead of hard coding a less than, which would then force your function to only work on integers (unless you type annotate to some other number type such as reals) instead of ''a (equality) values.
Thus what you wan't (to get the desired type), is something of the form:
fun searchBST t p x =
where t is the tree, p is your predicate function and x is the value you wan't to find. Basically what you are missing is to use the predicate function in the test, instead of doing it directly.
fun searchBST Empty _ _ = false
| searchBST (Node(l, d, r)) p x =
case (p(x, d), x < d) of
(true, _) => true
| (_, true) => searchBST l p x
| (_, false) => searchBST r p x

Your are missing this part in your code " (''a * ''a -> bool) " take it into consideration, work on the tuples then your code would work. the two ''a 's are the element your searching for and the element from the node.

Related

SML [circularity] error when doing recursion on lists

I'm trying to built a function that zips the 2 given function, ignoring the longer list's length.
fun zipTail L1 L2 =
let
fun helper buf L1 L2 = buf
| helper buf [x::rest1] [y::rest2] = helper ((x,y)::buf) rest1 rest2
in
reverse (helper [] L1 L2)
end
When I did this I got the error message:
Error: right-hand-side of clause doesn't agree with function result type [circularity]
I'm curious as of what a circularity error is and how should I fix this.
There are a number of problems here
1) In helper buf L1 L2 = buf, the pattern buf L1 L2 would match all possible inputs, rendering your next clause (once debugged) redundant. In context, I think that you meant helper buf [] [] = buf, but then you would run into problems of non-exhaustive matching in the case of lists of unequal sizes. The simplest fix would be to move the second clause (the one with x::rest1) into the top line and then have a second pattern to catch the cases in which at least one of the lists are empty.
2) [xs::rest] is a pattern which matches a list of 1 item where the item is a nonempty list. That isn't your attention. You need to use (,) rather than [,].
3) reverse should be rev.
Making these changes, your definition becomes:
fun zipTail L1 L2 =
let
fun helper buf (x::rest1) (y::rest2) = helper ((x,y)::buf) rest1 rest2
| helper buf rest1 rest2 = buf
in
rev (helper [] L1 L2)
end;
Which works as intended.
The error message itself is a bit hard to understand, but you can think of it like this. In
helper buf [x::rest1] [y::rest2] = helper ((x,y)::buf) rest1 rest2
the things in the brackets on the left hand side are lists of lists. So their type would be 'a list list where 'a is the type of x. In x::rest1 the type of rest1 would have to be 'a list Since rest1 also appears on the other side of the equals sign in the same position as [x::rest1] then the type of rest1 would have to be the same as the type of [x::rest1], which is 'a list list. Thus rest1 must be both 'a list and 'a list list, which is impossible.
The circularity comes from if you attempt to make sense of 'a list list = 'a list, you would need a type 'a with 'a = 'a list. This would be a type whose values consists of a list of values of the same type, and the values of the items in that list would have to themselves be lists of elements of the same type ... It is a viscous circle which never ends.
The problem with circularity shows up many other places.
You want (x::rest1) and not [x::rest1].
The problem is a syntactic misconception.
The pattern [foo] will match against a list with exactly one element in it, foo.
The pattern x::rest1 will match against a list with at least one element in it, x, and its (possibly empty) tail, rest1. This is the pattern you want. But the pattern contains an infix operator, so you need to add a parenthesis around it.
The combined pattern [x::rest1] will match against a list with exactly one element that is itself a list with at least one element. This pattern is valid, although overly specific, and does not provoke a type error in itself.
The reason you get a circularity error is that the compiler can't infer what the type of rest1 is. As it occurs on the right-hand side of the :: pattern constructor, it must be 'a list, and as it occurs all by itself, it must be 'a. Trying to unify 'a = 'a list is like finding solutions to the equation x = x + 1.
You might say "well, as long as 'a = 'a list list list list list ... infinitely, like ∞ = ∞ + 1, that's a solution." But the Damas-Hindley-Milner type system doesn't treat this infinite construction as a well-defined type. And creating the singleton list [[[...x...]]] would require an infinite amount of brackets, so it isn't entirely practical anyways.
Some simpler examples of circularity:
fun derp [x] = derp x: This is a simplification of your case where the pattern in the first argument of derp indicates a list, and the x indicates that the type of element in this list must be the same as the type of the list itself.
fun wat x = wat [x]: This is a very similar case where wat takes an argument of type 'a and calls itself with an argument of type 'a list. Naturally, 'a could be an 'a list, but then so must 'a list be an 'a list list, etc.
As I said, you're getting circularity because of a syntactic misconception wrt. list patterns. But circularity is not restricted to lists. They're a product of composed types and self-reference. Here's an example without lists taken from Function which applies its argument to itself?:
fun erg x = x x: Here, x can be thought of as having type 'a to begin with, but seeing it applied as a function to itself, it must also have type 'a -> 'b. But if 'a = 'a -> 'b, then 'a -> b = ('a -> 'b) -> 'b, and ('a -> 'b) -> b = (('a -> 'b) -> b) -> b, and so on. SML compilers are quick to determine that there are no solutions here.
This is not to say that functions with circular types are always useless. As newacct points out, turning purely anonymous functions into recursive ones actually requires this, like in the Y-combinator.
The built-in ListPair.zip
is usually tail-recursive, by the way.

Strong union of two lists

I've defined functions:
fun concaten(x,y) =
if (x = [])
then y
else hd(x) :: concaten(tl(x),y);
as well as:
fun existsin(x,L) =
if (L=[])
then false
else if (x = hd(L))
then true
else existsin(x,tl(L));
and am now trying to define a function of type (((list * list) -> list) -> list) that looks vaguely like the following:
fun strongunion(x,y) =
val xy = concaten(x,y);
if xy=[]
then []
if (existsin(hd(xy),tl(xy)) andalso x!= [])
then strongunion(tl(x),y)
else if (existsin(hd(xy),tl(xy)) andalso x = [])
then strongunion(x,tl(y))
else if (x != [])
then hd(xy) :: strongunion(tl(x),y)
else hd(xy) :: strongunion(x,tl(y));
which takes the "strong" union of two lists, i.e. it combats faulty inputs (lists with element duplicates). This code is, of course, syntactically invalid, but the reason I included it was to show what such a function would look like in an imperative language.
The way I started going about doing this was to first concatenate the lists, then remove duplicated elements from that concatenation (well, technically I am adding non-duplicates to an empty list, but these two operations are consequentially equivalent). To do this, I figured I would design the function to take two lists (type list*list), transform them into their concatenation (type list), then do the duplicate removal (type list), which would be of type (((list*list) -> list) -> list).
My issue is that I have no idea how to do this in SML. I'm required to use SML for a class for which I'm a TA, otherwise I wouldn't bother with it, and instead use something like Haskell. If someone can show me how to construct such higher-order functions, I should be able to take care of the rest, but I just haven't come across such constructions in my reading of SML literature.
I'm a bit unsure if strong union means anything other than just union. If you assume that a function union : ''a list * ''a list -> ''a list takes two lists of elements without duplicates as inputs, then you can make it produce the unions without duplicates by conditionally inserting each element from the one list into the other:
(* insert a single element into a list *)
fun insert (x, []) = [x]
| insert (x, xs as (y::ys)) =
if x = y
then xs
else y::insert(x, ys)
(* using manual recursion *)
fun union ([], ys) = ys
| union (x::xs, ys) = union (xs, insert (x, ys))
(* using higher-order list-combinator *)
fun union (xs, ys) = foldl insert ys xs
Trying this:
- val demo = union ([1,2,3,4], [3,4,5,6]);
> val demo = [3, 4, 5, 6, 1, 2] : int list
Note, however, that union wouldn't be a higher-order function, since it doesn't take functions as input or return functions. You could use a slightly stretched definition and make it curried, i.e. union : ''a list -> ''a list -> ''a list, and say that it's higher-order when partially applying it to only one list, e.g. like union [1,2,3]. It wouldn't even be fully polymorphic since it accepts only lists of types that can be compared (e.g. you can't take the union of two sets of functions).

Walking OCaml tuples of arbitrary depth

I'm trying to understand better the OCaml type inference. I created this example:
let rec f t = match t with
| (l,r) -> (f l)+(f r)
| _ -> 1
and I want to apply it on any binary tuple (pair) with nested pairs, to obtain the total number of leafs. Example: f ((1,2),3)
The function f refuses to compile, because a contradiction in types at (f l): "This expression has type 'a but an expression was expected of type 'a * 'b".
Question: 'a being any type, could not also be a pair, or else be handled by the _ case? Is any method to walk tuples of arbitrary depth without converting them to other data structures, such as variants?
PS: In C++ I would solve this kind of problem by creating two template functions "f", one to handle tuples and one other types.
There is a way to do this, although I wouldn't recommend it to a new user due to the resulting complexities. You should get used to writing regular OCaml first.
That said, you can walk arbitrary types in a generic way by capturing the necessary structure as a GADT. For this simple problem it is quite easy:
type 'a ty =
| Pair : 'a ty * 'b ty -> ('a * 'b) ty
| Other : 'a ty
let rec count_leaves : type a . a -> a ty -> int =
fun a ty ->
match ty with
| Pair (ta, tb) -> count_leaves (fst a) ta + count_leaves (snd a) tb
| Other -> 1
Notice how the pattern matching on the a ty here corresponds to the pattern matching on values in your (poorly typed) example function.
More useful functions could be written with a more complete type representation, although the machinery becomes heavy and complicated once arbitrary tuples, records, sum types, etc have to be supported.
Any combination of tuples will have a value shape completely described by it's type (because there is no "choice" in the type structure) - hence the "number of leaves" question can be answered completely statically at compile-time. Once you have a function operating on such type - this function is fixed to operate on that specific type (and shape) only.
If you want to build a tree that can have different shapes (but same type - hence can be handled by same function) - you need to add variants to the mix, i.e. classic type 'a tree = Leaf of 'a | Node of 'a tree * 'a tree, or any other type that describes value with some dynamic "choice" of shape.

SML: What does this this function guess : bool * ('a * 'a) -> 'a * 'a calculate?

From an old exam I had this SML function and I should give an answer on what this function calculates.
fun guess(e,(a,b)) = if e then (a,b) else (b,a)
The signature is bool * ('a * 'a) -> 'a * 'a but I have no clue what the purpose of this function is - despite the fact that it returns either (a,b) or (b,a).
Can anyone light me up?
If the condition is true it leaves (a,b) alone, otherwise it reverses it. There really isn't anything more to say about what it computes. As to borderline plausible motivation, sometimes ordered pairs need to be sorted in various ways. For example, guess(a<=b,(a,b)) will reverse (a,b) if a > b.

creat a tuple by removing first element from another tuple in ML

using ML as a programming language we have list and tuple, in the case of lists we can form a list from another list by removing or appending elements from and to the original list, for example if we have:
val x = [7,8,9] : int list
in REPL we can do some operations like the following:
- hd x;
val it = 7 : int
- tl x;
val it = [8,9] : int list
now if we have a tuple lets say:
val y = (7,8,9) :int*int*int
now the question is that , can we have a smaller tuple by removing the first element from the original tuple ? in other words , how to remove (#1 y) and have new tuple (8,9) in a similar way that we do it in the case of list.
Thanks.
Tuples are very different from lists. With lists, size need not be known at compile time, but with tuples, not only should the number of elements be known at compile time, the type of each element is independent of the others.
Take the type signature of tl:
- tl;
val it = fn : 'a list -> 'a list
It is 'a list -> 'a list - in other words tl takes a list of 'a and returns another one. Why don't we have one for tuples as well? Assume we wanted something like
y = (1,2,3);
tail y; (* returns (2,3) *)
Why does this not make sense? Think of the type signature of tail. What would it be?
In this case, it would clearly be
'a * 'b * 'c -> 'b * 'c
Takes product of an 'a, a 'b and a 'c and returns a product of
a 'b and a 'c. In ML, all functions defined must have a statically determined
type signature. It would be impossible to have a tail function for tuples that
handles all possible tuple sizes, because each tuple size is essentially a different type.
'a list
Can be the type of many kinds of lists: [1,2,3,4], or ["A", "short", "sentence"], or
[true, false, false, true, false]. In all these cases, the value of the type
variable 'a is bound to a different type. (int, string, and bool). And 'a list can be a list of any size.
But take tuples:
(1, true, "yes"); (* (int * bool * string) *)
("two", 2) (* (string, int) *)
("ok", "two", 2) (* (string, string, int) *)
Unlike list, these are all of different types. So while the type signature of all lists is simple ('a list), there is no 'common type' for all tuples - a 2-tuple has a different type from a 3-tuple.
So you'll have to do this instead:
y = (7, 8, 9);
(a, b, c) = y;
and a is your head and you can re-create the tail with (b,c).
Or create your own tail:
fun tail (a,b,c) = (b, c)
This also gives us an intuitive understanding as to why such a function would not make sense: If is impossible to define a single tail for use across all tuple types:
fun tail (a,b) = (b)
| tail (a,b,c) = (b, c) (* won't compile *)
You can also use the # shorthand to get at certain elements of the tuple:
#1 y; (* returns 7 *)
But note that #1 is not a function but a compile time shorthand.
Lists and tuples are immutable so there is no such thing like removing elements from them.
You can construct a new tuple by decomposing the original tuple. In SML, the preferred way is to use pattern matching:
fun getLastTwo (x, y, z) = (y, z)
If you like #n functions, you can use them as well:
val xyz = (7, 8, 9)
val yz = (#2 xyz, #3 xyz) (* (8, 9) *)