Question:
What is the logic behind comparing int lists using <, >, =? What about 'a lists?
Code:
# let x = [1] > [1]
val x : bool = false
# let x = [1;2] > [1]
val x : bool = true
# let x = [1;2] > [2;1]
val x : bool = false
# let x = [true;false] < [true;true]
val x : bool = true
Follow up questions:
when comparing two lists, how does the comparison work if the lists are not the same length? if the lists don't contain elements of the same type?
An ocaml list is represented by
type 'a my_list = Nil | Cons of 'a * 'a my_list
The Nil constructor is represented as an integer of value 0 while the Cons is a pointer to a block with tag 0 and 2 fields.
The < > = operators consider Nil < Cons. So if the lists are not the same length then the shorter list is smaller.
Comparison is always between the same types so lists of different types can't be compared (without Obj.magic).
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)
I am new to SML.
How do I use the AND operator inside IF statements?
Here is my code:
val y = 1;
val x = 2;
if (x = 1 AND y = 2) then print ("YES ") else print("NO ");
My error is:
stdIn:66.9-67.3 Error: unbound variable or constructor: AND
stdIn:66.3-67.9 Error: operator is not a function [literal]
operator: int
in expression:
1
stdIn:66.3-67.9 Error: operator and operand don't agree [literal]
operator domain: bool * bool
operand: bool * int
in expression:
x = (1 ) y = 2
Thank you
There is no AND operator in SML (unless you define one yourself). There is an and keyword, but you can't use it inside if statements (or generally as a part of any expression) because it's not an operator. It's used in combination with fun to define mutually recursive functions.
You're probably looking for the andalso operator, which takes two boolean operands and returns true if and only if both operands are true.
May I disagree with Vishal's comment?
*-true andalso true ;
val it = false : bool
-true andalso false ;
val it = false : bool*
I think (and so does the REPL) that
true andalso true ;
evaluates to true, not false
here is an example which will clear the usage of andalso
-true andalso true ;
val it = false : bool
- true andalso false ;
val it = false : bool
one and one in digital gates is always 1; therefore
in the above case true andalso true "must necessarily evaluate to true , not false; am'i correct ?
also 1 and 0 can't never be 1;
1 or 0 can be 1;
I have a function that return [[]], and I want to test the result as unit test.
But I found that the expression [[]] == [[]] return false.
Here a simple test code:
# [[]] == [[]];;
- : bool = false
Can someone explain me why this expression is evaluated as false?
Thanks.
Use = since you have structural equality for comparing two values:
# [[]] = [[]];;
- : bool = true
Because == is reference equality, it only returns true if you refer to the same memory location:
let a = [[]]
let b = a
# b == a;;
- : bool = true
The == operator in OCaml means "physical equality". However, you have two (physically) different lists. Probably, you want "structural equality", which is tested by =.
From what I can tell, = and != is supposed to work on strings in OCaml. I'm seeing strange results though which I would like to understand better.
When I compare two strings with = I get the results I expect:
# "steve" = "steve";;
- : bool = true
# "steve" = "rowe";;
- : bool = false
but when I try != I do not:
# "steve" != "rowe";;
- : bool = true
# "steve" != "steve";; (* unexpected - shouldn't this be false? *)
- : bool = true
Can anyone explain? Is there a better way to do this?
!= is not the negation of =. <> is the negation of = that you should use:
# "steve" <> "rowe" ;;
- : bool = true
# "steve" <> "steve" ;;
- : bool = false
#
!= is the negation of ==, and if you are an OCaml beginner, you should not be using any of these two yet. They can be a little tricky, and they are officially underspecified (the only guarantee is that if two values are == they are =).