Does != have meaning in OCaml? - ocaml

It seems to be an equivalency comparison for some types, but not strings.
# 3 != 3;;
- : bool = false
# 3 != 2;;
- : bool = true
This is as expected.
# "odp" = "odp";;
- : bool = true
# "odp" != "odp";;
- : bool = true
# "odp" <> "odp";;
- : bool = false
Why does "odp" != "odp" evaluate to true? What is it actually doing? Shouldn't it generate a type error?

you have experienced the difference between structural and physical equality.
<> is to = (structural equality) as != is to == (physical equality)
"odg" = "odg" (* true *)
"odg" == "odg" (* false *)
is false because each is instantiated in different memory locations, doing:
let v = "odg"
v == v (* true *)
v = v (* true *)
Most of the time you'll want to use = and <>.
edit about when structural and physical equality are equivalent:
You can use the what_is_it function and find out all the types that would be equal both structurally and physically. As mentioned in the comments below, and in the linked article, characters, integers, unit, empty list, and some instances of variant types will have this property.

The opposite for != operator is == operator, not the = one.
# "a" != "a" ;;
- : bool = true
# "a" == "a" ;;
- : bool = false
The == operator is a "physical equality". When you type "a" == "a", you compare two different instances of strings that happen to look alike, so the operator returns false. While having one instance makes it return true:
# let str = "a"
in str == str ;;
- : bool = true
# let str = "a"
in str != str ;;
- : bool = false

A quick explanation about == and != in OCaml in addition to all the correct answers that have already been provided:
1/ == and != expose implementation details that you really don't want to know about. Example:
# let x = Some [] ;;
val x : 'a list option = Some []
# let t = Array.create 1 x ;;
val t : '_a list option array = [|Some []|]
# x == t.(0) ;;
- : bool = true
So far, so good: x and t.(0) are physically equal because t.(0) contains a pointer to the same block that x is pointing to. This is what basic knowledge of the implementation dictates. BUT:
# let x = 1.125 ;;
val x : float = 1.125
# let t = Array.create 1 x ;;
val t : float array = [|1.125|]
# x == t.(0) ;;
- : bool = false
What you are seeing here are the results of an otherwise useful optimization involving floats.
2/ On the other hand, there is a safe way to use ==, and that is as a quick but incomplete way to check for structural equality.
If you are writing an equality function on binary trees
let equal t1 t2 =
match ...
checking t1 and t2 for physical equality is a quick way to detect that they are obviously structurally equal, without even having to recurse and read them. That is:
let equal t1 t2 =
if t1 == t2
then true
else
match ...
And if you keep in mind that in OCaml the “boolean or” operator is “lazy”,
let equal t1 t1 =
(t1 == t2) ||
match ...

They are like two "Tom"s in your class! Because:
In this case, "odp" = "odp"
because they are TWO strings with SAME VALUE!!
So they are not == because they are TWO different strings store in different (Memory) location
They are = because they have the identical string value.
One more step deeper, "odp" is anonymous variable. And two anonymous variable leads to this Two strings.
For your convenience:
# "odp" = "odp";;
- : bool = true
# "odp" != "odp";;
- : bool = true
# "odp" <> "odp";;
- : bool = false

ints are the only type where physical and structural equality are the same, because ints are the only type that is unboxed

Related

OCaml, comparing int lists using < > = operators

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).

Checking whether a given value exists in a binary tree

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)

How to use AND operator in IF statements in SML

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;

OCaml boolean expression [[]] == [[]]

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 =.

Unexpected results with OCaml !=

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 =).