OCaml physical and structural equality - ocaml

I understading than x == y is false because each is instantiated in different memory locations (https://stackoverflow.com/a/1412688/11439260). But i expected than a == b is false. Why this is true? How can I verify that there are two different let bindings?
(* First Examplle *)
let x = "odg"
let y = "odg"
x = y (* true *)
x == y (* false *)
(* Second example *)
let a = 1
let b = 1
a == b (* true, WHY? *)

One way to think of physical equality (==) is that it compares the addresses of the given values. Values in different memory locations have different addresses and will be physically unequal even if their values are structurally the same.
However an int is an immediate value in your OCaml implementation. In other words, there is no address involved. The int itself appears (in a tagged format) where you might expect the address to go. This means that any two ints that are structurally equal (=) are also physically equal (==).
Another way to say this is that ints aren't boxed (in your implementation and in all the ones I've seen).
Other integral values are boxed. (Note that 44l = 44 L, an int32 constant):
# 44l;;
- : int32 = 44l
# 44l = 44l;;
- : bool = true
# 44l == 44l;;
- : bool = false
Edit
As #octachron says, you really shouldn't write code that uses physical equality (==) on immutable values.
There is no guarantee about the behavior of == on immutable values other than that a == b implies a = b.

Another important point is that physical equality is not specified for immutable values. The result of
let xl = [0]
let yl = [0]
let whatever = xl == yl
will depend on how the code was compiled (or interpreted), and more generally on which compiler optimizations were applied or not. Typically with recent versions of OCaml, your string example x==y may return true because string are immutable by default since OCaml 4.06 .
In other words, you cannot use == to determine if two values were defined with the same bindings or not, because this notion is no part of the OCaml language and is not preserved by compiler optimizations.

Related

How can I place functions in a set in Ocaml?

I'd like make a Set module containing functions. But there seems to be no way to compare functions, which Set needs. This obvious-looking thing compiles:
module Action = struct
type t = unit -> unit
let compare : t -> t -> int = Stdlib.compare
end
module Actions = Set.Make(Action)
But if I attempt to use it:
Fatal error: exception Invalid_argument("compare: functional value")
I just want compare that the functions are the same object, I am not trying to do something silly like compare them for equal behaviour.
Am I supposed to use something from the Obj module here?
The semantics of Stdlib.compare is to look arbitrarily deep inside the objects to see how their subparts compare. This doesn't really work for functions, as you point out. So OCaml doesn't allow compare to be applied to functions.
There isn't really a useful order that can be applied to functions, even if you're willing to use physical equality. Function values are immutable and can be duplicated or moved physically by the runtime system, at least in theory.
Since the ordering would necessarily be arbitrary, you can get the same effect by making your own arbitrary order: pair the functions with an int value that increases monotonically as you create new pairs.
Add an identity to your actions, e.g., you can compare actions by name,
module Action = struct
type t = {
name : string;
func : (unit -> unit);
}
let compare x y = String.compare x.name y.name
end
You should also ensure that all actions have different names, for example by introducing a global hash table that records all created actions. Make sure that actions are only creatable via the Action module, by adding an appropriate signature.
OCaml Stdlib compare documentation states ...
val compare : 'a -> 'a -> int
compare x y returns 0 if x is equal to y, a negative integer if x is less than y, and a positive integer if x is greater than y. The ordering implemented by compare is compatible with the comparison predicates =, < and > defined above, with one difference on the treatment of the float value nan. Namely, the comparison predicates treat nan as different from any other float value, including itself; while compare treats nan as equal to itself and less than any other float value. This treatment of nan ensures that compare defines a total ordering relation.
compare applied to functional values may raise Invalid_argument. compare applied to cyclic structures may not terminate.
The compare function can be used as the comparison function required by the Set.Make and Map.Make functors, as well as the List.sort and Array.sort functions.
Now we have two notion(s) of equality in OCaml, namely...
Structural Equality: Expressed using operator =, the type of which is
# (=);;
- : 'a -> 'a -> bool = <fun>
Physical Equality: Expressed using operator ==, the type of which is
# (==);;
- : 'a -> 'a -> bool = <fun>
As we can see, the type of both is same, but the function application of both of them is different when it comes to function value as arguments.
Structural Equality doesn't hold over function values, but Physical Equality may. Trying to compare(as in =) with function values throws. And as stated in the documentation of Stdlib.compare, it uses structural equality.
Illustration: Structural Equality with Function Values
# let f x = x;;
val f : 'a -> 'a = <fun>
# let g x = x;;
val g : 'a -> 'a = <fun>
# f = g;;
Exception: Invalid_argument "compare: functional value".
# g = f;;
Exception: Invalid_argument "compare: functional value".
Illustration: Physical Equality with Function Values
# let f x = x;;
val f : 'a -> 'a = <fun>
# let g x = x;;
val g : 'a -> 'a = <fun>
# f == g;;
- : bool = false
# f == f;;
- : bool = true
# g == g;;
- : bool = true
# g == f;;
- : bool = false
# let h x y = x + y;;
val h : int -> int -> int = <fun>
# h == f;;
Error: This expression has type int -> int
but an expression was expected of type int -> int -> int
Type int is not compatible with type int -> int
So in short, I don't think we can use Stdlib.compare with Set.Make with function values.
So ...
Either, we will have to keep the type t in Action module to something over which structural equality can be applied if we have to continue using Stdlib.compare.
Or, implement compare of your own so that it can do something with those function values as arguments, along with satisfying the function contract of val compare : t -> t -> int as mandated by Set.OrderedType module type.
WYSIWYG => WHAT YOU SHOW IS WHAT YOU GET

When should extensible variant types be used in OCaml?

I took a course on OCaml before extensible variant types were introduced, and I don't know much about them. I have several questions:
(This question was deleted because it attracted a "not answerable objectively" close vote.)
What are the low-level consequences of using EVTs, such as performance, memory representation, and (un-)marshaling?
Note that my question is about extensible variant type specifically, unlike the question suggested as identical to this one (that question was asked prior to the introduction of EVTs!).
Extensible variants are quite different from standard variants in term of
runtime behavior.
In particular, extension constructors are runtime values that lives inside
the module where they were defined. For instance, in
type t = ..
module M = struct
type t +=A
end
open M
the second line define a new extension constructor value A and add it to the
existing extension constructors of M at runtime.
Contrarily, classical variants do not really exist at runtime.
It is possible to observe this difference by noticing that I can use
a mli-only compilation unit for classical variants:
(* classical.mli *)
type t = A
(* main.ml *)
let x = Classical.A
and then compile main.ml with
ocamlopt classical.mli main.ml
without troubles because there are no value involved in the Classical module.
Contrarily with extensible variants, this is not possible. If I have
(* ext.mli *)
type t = ..
type t+=A
(* main.ml *)
let x = Ext.A
then the command
ocamlopt ext.mli main.ml
fails with
Error: Required module `Ext' is unavailable
because the runtime value for the extension constructor Ext.A is missing.
You can also peek at both the name and the id of the extension constructor
using the Obj module to see those values
let a = [%extension_constructor A]
Obj.extension_name a;;
: string = "M.A"
Obj.extension_id a;;
: int = 144
(This id is quite brittle and its value it not particurlarly meaningful.)
An important point is that extension constructor are distinguished using their
memory location. Consequently, constructors with n arguments are implemented
as block with n+1 arguments where the first hidden argument is the extension
constructor:
type t += B of int
let x = B 0;;
Here, x contains two fields, and not one:
Obj.size (Obj.repr x);;
: int = 2
And the first field is the extension constructor B:
Obj.field (Obj.repr x) 0 == Obj.repr [%extension_constructor B];;
: bool = true
The previous statement also works for n=0: extensible variants are never
represented as a tagged integer, contrarily to classical variants.
Since marshalling does not preserve physical equality, it means that extensible
sum type cannot be marshalled without losing their identity. For instance, doing
a round trip with
let round_trip (x:'a):'a = Marshall.from_string (Marshall.to_string x []) 0
then testing the result with
type t += C
let is_c = function
| C -> true
| _ -> false
leads to a failure:
is_c (round_trip C)
: bool = false
because the round-trip allocated a new block when reading the marshalled value
This is the same problem which already existed with exceptions, since exceptions
are extensible variants.
This also means that pattern-matching on extensible type is quite different
at runtime. For instance, if I define a simple variant
type s = A of int | B of int
and define a function f as
let f = function
| A n | B n -> n
the compiler is smart enough to optimize this function to simply accessing the
the first field of the argument.
You can check with ocamlc -dlambda that the function above is represented in
the Lambda intermediary representation as:
(function param/1008 (field 0 param/1008)))
However, with extensible variants, not only we need a default pattern
type e = ..
type e += A of n | B of n
let g = function
| A n | B n -> n
| _ -> 0
but we also need to compare the argument with each extension constructor in the
match leading to a more complex lambda IR for the match
(function param/1009
(catch
(if (== (field 0 param/1009) A/1003) (exit 1 (field 1 param/1009))
(if (== (field 0 param/1009) B/1004) (exit 1 (field 1 param/1009))
0))
with (1 n/1007) n/1007)))
Finally, to conclude with an actual example of extensible variants,
in OCaml 4.08, the Format module replaced its string-based user-defined tags
with extensible variants.
This means that defining new tags looks like this:
First, we start with the actual definition of the new tags
type t = Format.stag = ..
type Format.stag += Warning | Error
Then the translation functions for those new tags are
let mark_open_stag tag =
match tag with
| Error -> "\x1b[31m" (* aka print the content of the tag in red *)
| Warning -> "\x1b[35m" (* ... in purple *)
| _ -> ""
let mark_close_stag _tag =
"\x1b[0m" (*reset *)
Installing the new tag is then done with
let enable ppf =
Format.pp_set_tags ppf true;
Format.pp_set_mark_tags ppf true;
Format.pp_set_formatter_stag_functions ppf
{ (Format.pp_get_formatter_stag_functions ppf ()) with
mark_open_stag; mark_close_stag }
With some helper function, printing with those new tags can be done with
Format.printf "This message is %a.#." error "important"
Format.printf "This one %a.#." warning "not so much"
Compared with string tags, there are few advantages:
less room for a spelling mistake
no need to serialize/deserialize potentially complex data
no mix up between different extension constructor with the same name.
chaining multiple user-defined mark_open_stag function is thus safe:
each function can only recognise their own extension constructors.

Remove real element from list - SML

I have written the following code:
fun remove_element(nil, elem) = raise Empty
| remove_element(hd::tl, elem) = if(hd=elem) then tl else hd::remove_element(tl, elem);
but that function (which removed element elem from list) works for int. I need to make it work for real numbers, but I can't do it. I have tried a lot of ways of rewriting the function and also I used :real but these bring me errors.
Any suggestions?
Thank you
The accepted answer should have allowed you to finish your assignment, so I will show two other approaches for variations of your problem without worrying about doing your homework for you. As Kevin Johnson said, it isn't possible to directly compare two reals. It is possible to do so indirectly since a=b if and only if a<=b and b<=a. Often this is a bug, especially if the list in question is of numbers produced by numerical computations. But -- there are some situations where it makes sense to compare reals for equality so you should certainly be able to do so as long as you are clear that this is what you want. This leads to the following modification of your code:
fun remove_real([],x:real) = []
| remove_real(y::ys,x) =
if (y <= x andalso y >= x) then
remove_real(ys,x)
else
y::remove_real(ys,x);
A few points:
1) I changed it to remove all occurrences of the element from the list rather than just the first occurrence. This involved changing the basis case to returning the empty list since [] with y removed is just [] rather than an error situation. Also, rather than simply returning the tail if the element is found I return the recursive call applied to the tail to remove any additional occurrences later on. You could easily modify the code to make it closer to your original code.
2) I needed to put the explicit type annotation x:real so that SML could infer that the list was of type real list rather than type int list.
3) I replaced nil by [] for aesthetic reasons
4) I replaced your pattern hd::tl by y::ys. For one thing, hd and tl are built-in functions -- I see no reason to bind those identifiers to anything else, even if it is just local to a function definition. For another thing, the less visual clutter in a pattern the better.
5) I made more use of white space. Partially a matter of taste, but I think that fairly complicated clauses (like your second line) should be split across multiple lines.
If you want to go the route of including an error tolerance for comparing reals, I think that it makes most sense to include the tolerance as an explicit parameter. I find |x-y| < e to be more natural than two inequalities. Unfortunately, the built-in abs only applies to ints. If x - y is real then the expression
if x - y < 0.0 then y - x else x - y
returns the absolute value of x - y (it flips the sign in the case that it is neagative). As an added bonus -- the comparison with 0.0 rather than 0 is all that SML needs to infer the type. This leads to:
fun remove_elem([],x,tol) = []
| remove_elem(y::ys,x,tol) =
if (if x - y < 0.0 then y - x else x - y) < tol then
remove_elem(ys,x,tol)
else
y::remove_elem(ys,x,tol);
Typical output:
- remove_real([2.0, 3.1, 3.14, 3.145, 3.14], 3.14);
val it = [2.0,3.1,3.145] : real list
- remove_elem([2.0, 3.1, 3.14, 3.145, 3.14], 3.14,0.01);
val it = [2.0,3.1] : real list
- remove_elem([2.0, 3.1, 3.14, 3.145, 3.14], 3.14,0.001);
val it = [2.0,3.1,3.145] : real list
The issue is here: hd=elem
In languages like ML and Javascript, you cannot directly compare two reals as reals are bound to rounding errors.
You have to use a lambda range and define an interval instead. elem - lambda < hd andalso elem + lambda > hd

Variable types for parameters in SML

fun in_list (x : int, y : int list) =
if null y
then false
else if x=hd y then true
else in_list(x,tl y)
This is what my code currently looks like, it simply returns true if x appears in the the y list, false if not. The issue is I want it to be able to input "a" and ["a", "b", "c"] as well, or even have x be a list, and y be a list of lists. I am VERY new to ML (just started learning about it last week), and have searched for answers and cannot come up with anything.
If you change the first line to
fun in_list (x : ''a, y : ''a list) =
then it will behave as you want. Here ''a is an equality type variable that can stand for any type that supports the = operator.
You could also just leave out the types altogether and the most general correct type will be inferred.
Types can always be omitted in function declarations, with is only one exception: where overloading of operators could cause ambiguity. An example is
fun square x = x*x
because the type of x could be either int or real. (It will default to int, maybe not what you want.)
The point is that there is only one function hd. But the operator * can refer to two quite different functions.

meaning of warning and type in ML

fun a(list) =
let
val num = length(hd(list))
fun inner(list) =
if num = length(hd(list)) then
if tl(list) = nil then true
else inner(tl(list))
else false
in
if length(hd(list))-1 = length(tl(list)) then inner(tl(list))
else false
end;
this is ml code and I got this warning and type.
stdIn:6.16 Warning: calling polyEqual
val a = fn : ''a list list -> bool
I don't understand about the warning. why it appear and the type. ''a why it has two '? ''?
what is the difference between 'a list list and ''a list list?
Excerpted from ML Hints:
Warning: calling polyEqual [may occur] whenever you use = to
compare two values with polymorphic type.
For example, fun eq(x,y) = (x = y); will cause this warning to be
generated, because x and y will have polymorphic type ''a. This
is perfectly fine and you may ignore the warning. It is not reporting
any kind of semantic error or type error in your code. The compiler
reports the warning because there can be a slight ineffeciency in how
ML tests whether two values of a polymorphic type are equal. In
particular, to perform the equality test, the run-time system must
first determine what types of values you are currently using and then
determine whether the values are equal. The first part (checking the
run-time types) can make the = test slightly slower than if the
types are known ahead of time (such as when we test 3 = 4 and know
that the = test is being applied to integers). However, that is not
something most users of ML ever need to worry about...
To answer your second question,
why it has two '? ''? what is the difference between 'a list list and
''a list list?
''a is the same as 'a, but requires it to be an equality type. An equality type in SML is a type that can be compared using =. Non-equality types cannot be compared using =. When you create a datatype, you can specify whether it is an equality type or not.
dict=val a =[("a",[1,2]),("b",[2,3])] ;
here is the code which has implementation of look up in dictionary
fun look key [] = []
| look key ((a,b)::xs) = if (key =a ) then b else look key xs ;
which gives output as
test1.sml:8.36 Warning: calling polyEqual
It is because it does not know what are the types which are compared so
the below code says that both are string type .
fun look (key:string) [] = []
| look (key:string) ((a:string,b)::xs) = if (key =a ) then b else look (key:string) xs ;