Let's say I have a bunch of nested let...in statements. I noticed that if I have
(* a bunch of let... in above *)
let test = expr1 in
(* a bunch of let ... in below *)
I get this Error (warning 26): unused variable test, yet when I change it to let _ = expr1 in ... or let () = expr1 in ... there are no error messages.
I understand let _ = is pattern matching for anything and let () = is pattern matching for anything of type unit, but does this mean that my expr1 is just being executed anywhere? Is it being called once?
There's a very simple experiment you can do do test this:
let test = print_endline "named";;
let _ = print_endline "any pattern";;
let () = print_endline "unit";;
As you can see, whether you put this in a source file and compile it or run it in the toplevel, it will print each string exactly once.
OCaml is a strictly evaluated (more specifically, call by value) language with side-effects, which means it will evaluate expressions in order, and not optimize away code with potential side-effects.
Related
Background
I'm a relative newcomer to Reason, and have been pleasantly suprised by how easy it is to compare variants that take parameters:
type t = Header | Int(int) | String(string) | Ints(list(int)) | Strings(list(string)) | Footer;
Comparing different variants is nice and predictable:
/* not equal */
Header == Footer
Int(1) == Footer
Int(1) == Int(2)
/* equal */
Int(1) == Int(1)
This even works for complex types:
/* equal */
Strings(["Hello", "World"]) == Strings(["Hello", "World"])
/* not equal */
Strings(["Hello", "World"]) == Strings(["a", "b"])
Question
Is it possible to compare the Type Constructor only, either through an existing built-in operator/function I've not been able to find, or some other language construct?
let a = String("a");
let b = String("b");
/* not equal */
a == b
/* for sake of argument, I want to consider all `String(_)` equal, but how? */
It is possible by inspecting the internal representation of the values, but I wouldn't recommend doing so as it's rather fragile and I'm not sure what guarantees are made across compiler versions and various back-ends for internals such as these. Instead I'd suggest either writing hand-built functions, or using some ppx to generate the same kind of code you'd write by hand.
But that's no fun, so all that being said, this should do what you want, using the scarcely documented Obj module:
let equal_tag = (a: 'a, b: 'a) => {
let a = Obj.repr(a);
let b = Obj.repr(b);
switch (Obj.is_block(a), Obj.is_block(b)) {
| (true, true) => Obj.tag(a) == Obj.tag(b)
| (false, false) => a == b
| _ => false
};
};
where
equal_tag(Header, Footer) == false;
equal_tag(Header, Int(1)) == false;
equal_tag(String("a"), String("b")) == true;
equal_tag(Int(0), Int(0)) == true;
To understand how this function works you need to understand how OCaml represents values internally. This is described in the section on Representation of OCaml data types in the OCaml manual's chapter on Interfacing C with OCaml (and already here we see indications that this might not hold for the various JavaScript back-ends, for example, although I believe it does for now at least. I've tested this with BuckleScript/rescript, and js_of_ocaml tends to follow internals closer.)
Specifically, this section says the following about the representation of variants:
type t =
| A (* First constant constructor -> integer "Val_int(0)" *)
| B of string (* First non-constant constructor -> block with tag 0 *)
| C (* Second constant constructor -> integer "Val_int(1)" *)
| D of bool (* Second non-constant constructor -> block with tag 1 *)
| E of t * t (* Third non-constant constructor -> block with tag 2 *)
That is, constructors without a payload are represented directly as integers, while those with payloads are represented as "block"s with tags. Also note that block and non-block tags are independent, so we can't first extract some "universal" tag value from the values that we then compare. Instead we have to check whether they're both blocks or not, and then compare their tags.
Finally, note that while this function will accept values of any type, it is written only with variants in mind. Comparing values of other types is likely to yield unexpected results. That's another good reason to not use this.
I have this code:
cnf.mli
type literal
type clause
type cnf
type l_diff
val l_compare: literal -> literal -> l_diff
cnf.ml (partial)
type l_diff = Same | Negation | Different
checker.ml (partial)
open Cnf
type solution = (literal * bool) list
let rec solve_literal sol l =
match sol with
| [] -> false
| (hl, b)::rs when (l_compare l hl) = Same -> b
| (hl, b)::rs when (l_compare l hl) = Negation -> not b
| _::rs -> solve_literal rs l
This works in utop using:
#mod_use "cnf.ml";;
#use "checker.ml";;
But if I try to compile checker I get the following error:
compile command:
ocamlbuild cnf.cma
ocamlbuild checker.cma
error:
+ /home/user/.opam/4.05.0/bin/ocamlc.opt -c -o checker.cmo checker.ml
File "checker.ml", line 7, characters 42-46:
Error: Unbound constructor Same
Hint: Did you mean Some?
Command exited with code 2.
Compilation unsuccessful after building 6 targets (2 cached) in 00:00:00.
Am I using a variant the wrong way, or using the compiler incorrectly?
Neither, you are using abstract types in signature in the wrong way. When you write in cnf.mli
type l_diff
this declares the type l_diff as an abstract type, in other words a black box whose content is hidden.
Contrarily, when using #mod_use "cnf.ml" the toplevel infers a signature by itself and makes all type declarations transparent:
type literal = …
type clause = …
type cnf = …
type l_diff = Same | Negation | Different
val l_compare: literal -> literal -> l_diff
(If you want to see the full inferred signature ocamlbuild cnf.inferred.mli should work.)
With this signature, the constructor of l_diff are visible and it becomes possible to construct directly or pattern match values of type l_diff.
More generally, your signature cnf.mli is far too restrictive:
With this signature, the only way to create a value of type l_diff is to call l_compare. However it would be then impossible to observe the content of the type. Similarly, with the interface cnf.mli that you provided, it is impossible to create a value of type literal.
Using the OUnit unit testing framework in OCaml, I would like to test that the result of evaluating a function is an instance of a specified type.
Defining such a test in Python's PyTest would be done as follows:
def test_foo():
assert isinstance(foo(2), int)
How can this logic be translated to OUnit? That is, how are assertions of type membership specified?
I'm aware that, assuming the function under test is annotated with the proper type signature, this testing might be unnecessary.
This is the job of a type checker, and it is made automatically during the compilation (at static time). The type checker (i.e., the compiler) guarantees that all values that are created by a function has the same type, and the type is defined statically at the compilation time. You will not be able to compile a function, that creates values of different types, as you will get a type error during the compilation. This is an essential property of all statically typed languages, e.g., Java, C and C++ also has the same property.
So, probably, you're using are confusing terminology. It might be the case, that what you're actually trying to test, is that the value belongs to a particular variant of a sum type. For example, if you have a sum type called numbers defined as:
type t =
| Float of float
| Int of int
and you would like to test that function truncate, defined as
let truncate = function
| Float x -> Int (truncate x)
| x -> x
always returns the Int variant, then you can do this as follows:
let is_float = function Float _ -> true | _ -> false
let is_int = function Int _ -> true | _ -> false
assert (is_int (truncate 3.14))
There are codes like
let () = print_string "something" in
fn
in some OCaml codes.
What does this mean? Is there special meaning on "()"? or Is it same meaning as
print_string "something";
fn
There's nothing special about () in this let expression, it's just a pattern. All let expressions look like let pattern = expression in other-expression. Here the pattern will always match, because print_string returns unit, and () is the only value of that type. In this way, it's just another way of combining two expressions into one when the first one is really more of a statement (returns unit).
So you're right, the construct has pretty much the same meaning as using the ; operator. The only real difference is in the precedence. If, for example, you write
if x < 3 then
print_string "something";
f x
you would find that f x is always called. The precedence of ; is too low to pull the second expression under the control of the if. That's the reason many people (including me) get into the habit of using let () = expression. If you write the above as
if x < 3 then
let () = print_string "something"
in f x
the f x is only called when x is less than 3, which is usually what I want. In essence, the precedence of let is much higher than ;.
Of course there are may other ways to get this effect, but the nice thing about using let is that you don't have to add anything later on in the code (like a closing parenthesis or an end). If you're adding the print_string as a debugging statement, this is a handy way of keeping the changes local to the one spot.
Jeffrey's answer is absolutely correct, but one more point:
if you write
fx "something";
fn
And you messed up the result type of fx "something" the compiler will emit a Warning, that might get lost during compilation. On the other hand if you write:
let () = fx "something" in
fn
The compiler will type check that the result of fx "something" can be matched against (), i.e. that it is really of type unit. Thus if you messed up an error is produced, which is usually more secure.
There also is the possibility to write
let _ = fx "something" in
fn
which will only get the precedence effect that Jeffrey mentioned, but not do any type checking, since _ can be matched against values of any type.
This is my error:
Error: This expression has type nfa but is here used with type nfa
What could possibly be happening to cause this? I'm using emacs tuareg, and loading evaluating files one by one. Sometimes this happens, and other times it doesn't.
There's a good description of this in the ocaml tutorial. What's happened is you have shadowed a type definition with a new definition:
type nfa = int
let f (x: nfa) = x
type nfa = int
let g (x: nfa) = x
Restarting the top-level will clear out the old definitions.
Update:
Since OCaml 4.01.0 (released Sept. 2013) the general problem is the same, but the error message adds a number to the type definition, to make evident the types are internally different.
Full example from the old OCaml FAQ in the toplevel:
type counter = Counter of int;; (* define a type *)
type counter = Counter of int
# let x = Counter 1;; (* use the new type *)
val x : counter = Counter 1
type counter = Counter of int;; (* redefine the type, use it *)
type counter = Counter of int
# let incr_counter c = match c with Counter x -> Counter (x + 1);;
val incr_counter : counter -> counter = <fun>
# incr_counter x;; (* now mix old and new defs *)
Error: This expression has type counter/1029
but an expression was expected of type counter/1032
#