I am new to SML. I am trying to check whether a given value exist in the binary tree or not. Below is the snippet of the code. Upon execution it gives
Warning : match nonexhaustive (n,Node (t1, j, t2)) => ...
I cannot understand why it is showing this way. I guess I have covered all possible case. Can anyone give me hint or link which will be helpful to remove this warning.
datatype inttree = Empty | Node of inttree * int * inttree;
(*find(n,K) here n is the key that we have to find in inttree K*)
val rec find = fn(n, Node(t1,j,t2)) =>
let
val t = Node(t1, j, t2)
val compare = fn(i,j) => i = j
val find' =
fn (n,Empty) => false (* if we have reached the empty node then we are not able to find the key therefore return false *)
| (n,Node(t1,j,t2)) =>
if compare(n,j)
then true (* if value n and j are equal we have found the key n in the tree*)
else find(n,t1) orelse find(n,t2) (* if the value is not equal check in left subtree if found return true else check in the right subtree*)
in
find'(n,t)
end;
Given your datatype declaration, a fairly direct recursive approach is possible. Since this seems to be homework, I don't want to give a complete solution, but here is a function which has a similar flavor:
fun allEven Empty = true
| allEven (Node(t1,i,t2)) =
if i mod 2 = 1 then false
else allEven t1 andalso allEven t2;
This function returns true or false depending on whether or not all integers in the tree are even. It has a basis case
allEven Empty = true
(true since there are no odd numbers in an empty tree to serve as counter-examples) and a recursive case
allEven (Node(t1,i,t2)) =
if i mod 2 = 1 then false
else allEven t1 andalso allEven t2;
If the integer at the node is odd, return false -- otherwise return true if the recursive call to both branches evaluate to true.
Typical runs:
- allEven (Node(Node(Empty,3,Empty),5,Node(Node(Empty,6,Empty),7,Empty)));
val it = false : bool
- allEven (Node(Node(Empty,4,Empty),2,Node(Node(Empty,6,Empty),8,Empty)));
val it = true : bool
Your function should be about this long and follow the same basic recursive pattern.
Besides val rec, you can also write fun and specify the arguments on the left-hand side of the =.
The helper function compare is largely redundant. You might as well use =. Also, what one would call a compare function in ML is usually one that returns the type order, having the values LESS, EQUALS and GREATER:
- Int.compare (3, 5);
> val it = LESS : order
When writing an if ... then true else ... or similar statement that returns the type bool, you might as well just use the combinators orelse and andalso. For example, you can replace the following:
if compare(n,j)
then true
else find(n,t1) orelse find(n,t2)
with:
n = j orelse find (n, t1) orelse find (n, t2)
Much like the built-in functions List.exists and List.all take a function as predicate and scans a list in the attempt to prove either that at least one element exists for which this is true, or that it is true for all elements, you can make functions treeExists and treeForall:
datatype intTree = Empty | Node of inttree * int * inttree;
fun treeExists f Empty = false
| treeExists f (Node (leftTree, x, rightTree)) =
f x orelse treeExists f leftTree orelse treeExists f rightTree
fun treeForall f Empty = true
| treeForall f (Node (leftTree, x, rightTree)) =
f x andalso treeForall f leftTree andalso treeExists f rightTree
Making functions find and allEven has now become simpler:
fun find (x, tree) = treeExists (fn y => x = y) tree
fun allEven tree = treeForall (fn x => x mod 2 = 0) tree
since all the recursion has been left to new library functions.
In a similar way, you can make treeMap and treeFold:
fun treeMap f Empty = Empty
| treeMap f (Node (leftTree, x, rightTree)) = ...
fun treeFold f e Empty = e
| treeFold f e (Node (leftTree, x, rightTree)) = ...
They could be used to find the largest absolute value in a tree:
fun maxAbsTree tree =
treeFold Int.max 0 (treeMap Int.abs tree)
Related
I have a datatype in this way
datatype 'a bin_tree =
Leaf of 'a
| Node of 'a bin_tree (* left tree *)
* int (* size of left tree *)
* int (* size of right tree *)
* 'a bin_tree (* right tree *)
so an example for correct tree would be:
val tree1 =
Node(Node(Node(Leaf 47, 1, 1, Leaf 38),
2,1,
Leaf 55),
3,2,
Node(Leaf 27, 1, 1, Leaf 96))
and an example for violating tree would be
val tree1false =
Node(Node(Node(Leaf 47, 1, 1, Leaf 38),
2,1,
Leaf 55),
4,2,
Node(Leaf 27, 1, 1, Leaf 96))
How can I write a predicate test such that
- test tree1;
val it = true : bool
- test tree1false;
val it = false : bool
This is a recursive problem. Before solving recursive problems on trees, it is a good idea to have a firm grasp on recursion on lists. You could say that trees are generalisations of lists, or that lists are special-cases of trees: lists have one tail, trees can have any number of tails depending on the type of tree. So here is how you could reconstruct and solve the problem using lists:
If, instead of the typical list definition, you have a list that also memoizes its own length:
(* datatype 'a list = [] | :: of 'a * 'a list *)
datatype 'a lenlist = Nil | Cons of int * 'a * 'a lenlist
Then you can test that the stored length is in accordance with the actual number of values.
I'll start by creating a function that counts to illustrate the part of the function that performs recursion:
(* For regular built-in lists *)
fun count0 [] = 0
| count0 (x::xs) = 1 + count0 xs
(* Counting the memoized list type disregarding the n *)
fun count1 Nil = 0
| count1 (Cons (n, x, xs)) = 1 + count1 xs
The next part is that I'd like, in each recursive step, to test that the stored number n is also in accordance with the actual counting. What is the return type of this function? Well, the test function that you want should be 'a lenlist -> bool and the count function that I made is 'a lenlist -> int.
I will suggest that you make a testcount that kinda does both. But you can do so in many ways, e.g. by giving it "extra arguments", or by giving it "extra return values". I will demonstrate both, just to show that sometimes one is better than the other and experience will tell you which.
Here is a val testcount1 : 'a lenlist -> bool * int function:
fun testcount1 Nil = (true, 0)
| testcount1 (Cons (n, x, xs)) =
let val (good_so_far, m) = testcount1 xs
val still_good = good_so_far andalso n = m + 1
in (still_good, m + 1)
end
val goodList = Cons (4, #"c", Cons (3, #"o", Cons (2, #"o", Cons (1, #"l", Nil))))
val badList = Cons (3, #"d", Cons (2, #"e", Cons (1, #"r", Cons (0, #"p", Nil))))
Testing this,
- testcount1 goodList;
> val it = (true, 4) : bool * int
- testcount1 badList;
> val it = (false, 4) : bool * int
This shows that testcount1 returns whether the numbers add up and the list's actual length, which was necessary during recursion to test that the numbers add up in each step, but in the end is no longer necessary. You could wrap this testcount function up in a simpler test function that only cares about the bool:
fun test xs = #1 (testcount1 xs)
Here is another way to go about: There is something not so satisfying with the way testcount1 recurses. It keeps calculating the m + 1s even though it is able to determine that a list (e.g. at Cons (0, #"p", Nil)) is broken.
Here is an alternate val testcount2 : 'a lenlist * int -> bool that stores a number in an extra argument instead:
fun testcount2 (Nil, 0) = true
| testcount2 (Nil, _) = false
| testcount2 (Cons (n, x, xs), m) =
n = m andalso testcount2 (xs, m - 1)
This seems a lot neater to me: The function is tail-recursive, and it stops immediately when it senses that something is fishy. So it doesn't need to traverse the entire list if it's broken at the head. The downside is that it needs to know the length, which we don't know yet. But we can compensate by assuming that whatever is advertised is correct until it's clearly the case, or not.
Testing this function, you need to not only give it a goodList or a badList but also an m:
- testcount2 (goodList, 4);
> val it = true : bool
- testcount2 (badList, 4);
> val it = false : bool
- testcount2 (badList, 3);
> val it = false : bool
It's important that this function doesn't just compare n = m, since in badList, that'd result in agreeing that badList is 3 elements long, since n = m is true for each iteration in all Cons cases. This is helped in the two Nil cases that require us to have reached 0 and not e.g. ~1 as is the case for badList.
This function can also be wrapped inside test to hide the fact that we feed it an extra argument derived from the 'a lenlist itself:
fun size Nil = 0
| size (Cons (n, _, _)) = n
fun test xs = testcount2 (xs, size xs)
Some morals so far:
Sometimes it is necessary to create helper functions to solve your initial problem.
Those helper functions are not restricted to have the same type signature as the function you deliver (whether this is for an exercise in school, or for an external API/library).
Sometimes it helps to extend the type that your function returns.
Sometimes it helps to extend the arguments of your functions.
Just because your task is "Write a function foo -> bar", this does not mean that you cannot create this by composing functions that return a great deal more or less than foo or bar.
Now, for some hints for solving this on binary trees:
Repeating the data type,
datatype 'a bin_tree =
Leaf of 'a
| Node of 'a bin_tree (* left tree *)
* int (* size of left tree *)
* int (* size of right tree *)
* 'a bin_tree (* right tree *)
You can start by constructing a skeleton for your function based on the ideas above:
fun testcount3 (Leaf x, ...) = ...
| testcount3 (Leaf x, ...) = ...
| testcount3 (Node (left, leftC, rightC, right), ...) = ...
I've embedded som hints here:
Your solution should probably contain pattern matches against Leaf x and Node (left, leftC, rightC, right). And given the "extra argument" type of solution (which at least proved nice for lists, but we'll see) needed two Leaf x cases. Why was that?
If, in the case of lists, the "extra argument" m represents the expected length of the list, then what would an "extra argument" represent in the case of trees? You can't say "it's the length of the list", since it's a tree. How do you capture the part where a tree branches?
If this is still too difficult, consider solving the problem for lists without copy-pasting. That is, you're allowed to look at the solutions in this answer (but try not to), but you're not allowed to copy-paste code. You have to type it if you want to copy it.
As a start, try to define the helper function size that was used to produce test from testcount2, but for trees. So maybe call it sizeTree to avoid the name overlap, but other than that, try and make it resemble. Here's a skeleton:
fun sizeTree (Leaf x) = ...
| sizeTree (Node (left, leftC, rightC, right)) = ...
Sticking testcount3 and sizeTree together, once written, should be easy as tau.
Working on a small assignment for class, having a lot of trouble with Haskell. I am trying to make a recursive method for finding if an integer is part of a list or not. I know the gist, but am unable to get it working correctly with the haskell syntax. Check if the current list is empty, if so then False, then check if integer is equal to the head of the current list, if so, then True, then call member again with the same value you are searching for, and the tail of the list. What can I do to get this functioning properly.
Currently this is what I have:
member ::Int -> [Int] -> Bool
member x y
if y [] then False
else if x == head y then True
else member x tail y
I have also tried using
member :: (Eq x) => x -> [x] -> Bool
as the beginning line, and also a much simplier :
let member x y = if null y then False
else if x == head y then True
else member x tail y
Any help would be appreciated.
with pattern matching you can write it more clearly
member :: (Eq a) => a -> [a] -> Bool
member x [] = False
member x (y:ys) | x==y = True
| otherwise = member x ys
element _ [] = False
element e (x:xs) = e == x || e `element` xs
-- OR
element e xs = if xs == [] then False
else if e == head xs then True
else e `element` tail xs
-- OR
element e xs = xs /= [] && (e == head xs || e `element` tail xs)
-- x `op` y = op x y
-- If you're feeling cheeky
element = elem
Your syntax appears very confused, but your logic makes sense, so here's a bucket list of things to remember:
Functions can be defined by multiple equations. Equations are checked top to bottom. That means using =.
Pattern matches are not equality tests. A pattern match breaks a value into its constituents if it matches and fails otherwise. An equality test x == y returns a Bool about the equality of x and y.
Pattern matching is used for flow control via...
a case statement, like
case xs of {
[] -> ...
x:xs' -> ...
}
Multiple equations, like
element _ [] = ...
element e (x:xs) = ...
Note that you can ignore a value in a pattern with _. With multiple equations of a function with multiple arguments, you're really pattern matching on all the arguments at once.
Bools are used for flow control via if _ then _ else _:
if xs == [] then False
else True
which is really just
case x == y of {
True -> False
False -> True
}
and Bools can use the ordinary operators (&&) (infixr 3) and (||) (infixr 2)
The difference is especially nefarious on lists. instance Eq a => Eq [a], so in order to use == on lists, you need to know that the elements of the lists can be compared for equality, too. This is true even when you're just checking (== []). [] == [] actually causes an error, because the compiler cannot tell what type the elements are. Here it doesn't matter, but if you say, e.g. nonEmpty xs = xs /= [], you'll get nonEmpty :: Eq a => [a] -> Bool instead of nonEmpty :: [a] -> Bool, so nonEmpty [not] gives a type error when it should be True.
Function application has the highest precedence, and is left-associative:
element x xs reads as ((element x) xs)
element x tail xs reads as (((element x) tail) xs), which doesn't make sense here
f $ x = f x, but it's infixr 0, which means it basically reverses the rules and acts like a big set of parentheses around its right argument
element x $ tail xs reads as ((element x) (tail xs)), which works
Infix functions always have lower precedence than prefix application:
x `element` tail xs means ((element x) (tail xs)), too
let decls in expr is an expression. decls is only in scope inside expr, and the entire thing evaluates to whatever expr evaluates to. It makes no sense on the top level.
Haskell uses indentation to structure code, like Python. Reference
I am new to ruby and working on a problem but I don't know how to figure it out.
I want to write a function that return true if each consecutive element is a power of the previous element, otherwise return false
for example: if I have a list [2;4;8;16] the function should return true
function should return false , [3; 7; 9;]
let consec_ele element = match element with
[] -> true
h::t ->
if h > t then false
else
if t/h = 0 && t mod h = 0 then true
;;
i just can't figure out how to make it work and that so recursively.
Well, you first need to formalise your problem :
if my list is empty, then true
if my list is not, then it starts with a number n
if n = 1, then I need to start again because a^0 = 1 for all a
if n > 0 then I call a new function check on the rest of the list, tl, acting like this :
if tl is empty, then true
else tl starts with n' then if n' = n * n then I call check recursively on the rest and I need to keep the fact that I'm now checking for n * n * n ...
If n <= 0 then false
In OCaml this would be
let consec_ele l =
let rec cer b = function
| [] -> true
| n :: tl ->
if n <= 0 then false
(* We can start again for the first 1 we see, but if our
* list is [1; 1; 1; ...; 1] then we need to stop
* That's why we have this boolean b which is true and once
* we see 1 as the head of our list we swap it to false
*)
else if n = 1 then b && cer false tl
else
let rec check p = function
| [] -> true
| n' :: tl -> n' = pow n p && check (p + 1) tl
in check 1 tl
in cer true l;;
(For the pow function, I let you write it ;-) Of course, this can be bad because you could have an overflow, maybe you'd prefer to see if n' ^ (1/p) = n (the pth root of n' (why don't we have LaTeX mathmode on stackoverflow ? :-())
Being able to pattern-match on the first two elements in a list makes this trivial. Obviously an empty list is true, and a list with one element is also true. Otherwise, if we consider the first two elements, if the second is a power of the first, the function is true, and we can discard the first and consider the rest of the list recursively. Otherwise, the result is clearly false.
let rec consec_ele =
function
| [] | [_] -> true
| a::(b::_ as tl) when is_power_of a b -> consec_ele tl
| _ -> false
As a note, your test case of [2;4;8;16] should actually return false as 8 is a multiple, but not a power of 4.
I wrote a function that is supposed to receive a list of tuples. I access the components of the tuples with # and the code compiles:
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
But another function that basically does the same thing, namely receiving a list of tuples and accessing those, causes an error.
fun validate ([]) = true
| validate (h::t) =
if 1 = (#1 h) then
true
else
false
Can't find a fixed record type. Found near #1
What is the difference here and why does the latter cause an error?
Edit
The first function actually does not compile on its own.
But this entire snippet does:
fun drop ([], n) = []
| drop (h::t, 0) = h::t
| drop (h::t, n) =
drop(t, n-1)
fun sts_linear (y, n) =
if y < (Math.sqrt(n)+1.0) then
let
(* x^2 + y^2 = n => x = sqrt(n-y^2) *)
val x = Math.sqrt(n - (y * y));
val xr = Real.realRound(x);
in
if (abs(x - xr) < 0.000000001) then
[(Real.trunc xr, Real.trunc y)]#sts_linear (y+1.0, n)
else
(
[]#sts_linear (y+1.0, n)
)
end
else []
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
fun sts (n) =
(
let
val pairs = sts_linear(0.0, Real.fromInt n);
in
recheck(drop(pairs, Real.ceil( Real.fromInt (length(pairs))/2.0 ) ), n)
end
)
Your first code doesn't compile, at least with SML/NJ:
If you got it to compile then it must have been in a nonstandard extension of SML.
The problem with both of your definitions is that there is no polymorphic idea of a tuple of arbitrary arity in SML. You can write functions to work on lists of pairs. You can write functions to work on lists of triples. But -- you can't write functions to work simultaneously on lists of pairs and lists of triples (at least if your function tries to do things with these pairs/triples as tuples).
One solution is to get rid of # and use pattern-matching to extract the components:
fun validate [] = true
| validate ((x,y)::t) =
if x = 1 then
true
else
false
But, if you really want to write a function which can polymorphically apply to either lists of pairs or list of triples (or quadruples,...), the easiest thing to do is to represent the pairs, triples, etc. as lists rather than tuples. Lists which contains lists of nonspecified size are not a problem in SML.
Trying to minimize this down, as I have seen the following work in SML/NJ
and i'm not aware of it actually being a compiler extension
val p1 = {x=0, y=0};
val p2 = {x=1, y=1};
val p3 = {x=1, y=1, z=1};
There is an awkward construct from a compiler error perspective
not many languages have errors that work in this fashion,
because the function is valid, but produces a type error
unless an invocation of the function exists to resolve the
type of 'record', thus to resolve the error more code must be added.
fun getFoo(field) = fn record => field record;
Without the following actual calling of the getX
the compiler cannot determine the type of record
of which the complete type information of ALL fields
of the record must be known to the compiler, not just the #x field.
let val getX = getFoo(#x);
val x1 = getX(p1);
val x2 = getX(p2);
val x3 = getFoo(#x)(p3);
in () end;
while the following commented out snippet results in an error because the types of
p1 and p3 are different, and so different invocations of getFoo
are required
(*
let val getX = getFoo(#x);
val x1 = getX(p1);
val x3 = getX(p3);
in () end;
*)
and the following is insufficient since it never resolves the record.
let val getX = getFoo(#x) in () end;
I've come across 2 confusing problems in SML and was hoping someone could help me out:
The first is a function which takes an element and a list and decides whether that element exists in the list or not, here is the code I've attempted to write:
fun member (e,L) = foldl (fn(a,b) => if (e = b) then true else false) false L;
But I get bool * 'a list --> bool but what I need is ''a * ''a list --> bool
As for the second, it also requires an element and a list but returns a list of elements less than the passed one. I'm not sure whether this should be done via map or foldr/foldl.
Any suggestions?
Thanks in advance :)
Regarding the first question, in fn (a, b) => ... a is the next element and b is the accumulator. Since you compare e with b, e is infered to have type bool. You should compare e with a, and never override b when it becomes true:
fun exists (e, L) =
foldl (fn (a, b) => e = a orelse b) false L
For the second question, you can use foldr/foldl to do so. It's similar to the first example; you start with empty list as the accumulator and prepend an element to it whenever that element is smaller than a threshold.
As a tradeoff, foldr gives you the right order but it isn't tail-recursive. On the other hand, foldl is tail-recursive but gives resulting lists in a reverse order.
to see if an element is in list or not try this:
fun elementExist(e, nil) = false
| elementExist(e, x::xs) = if e = x orelse elementExist(e, xs) then true else false;
for the second one to remove the existing element from the list:
fun elFromList(e, nil) = []
| elFromList(e, x::xs) = if e = x then elFromList(e, xs) else x::elFromList(e, xs);
Good Luck!!