Code compiling on OCaml 3.11 but not on 4.01 - ocaml

I have the following code that compiles fine in OCaml 3.11:
module type T =
sig
type test
val create : int -> test (* line 44 *)
...
end
...
type test = (string, clause list) Hashtbl.t
let create = Hashtbl.create (* line 332 *)
But when I try to compile it with OCaml 4.01, it gives me the following error:
Error: Signature mismatch:
...
Values do not match:
val create : ?random:bool -> int -> ('a, 'b) Hashtbl.t
is not included in
val create : int -> theory
File "test1.ml", line 44, characters 2-28: Expected declaration
File "test1.ml", line 332, characters 6-12: Actual declaration
make[1]: *** [test1.cmo] Error 2
make: *** [byte-code] Error 2
What changed in OCaml 4 so that it now can't compile it? I am sure it has a very easy explanation but I am still learning the inner workings of OCaml types.

The type of the function has changed --of course! Since the addition is of an optional argument, it will affect anyone who is aliasing the function (which will carry over the type, inc. the optional parameter). You will have to eta-expand the arguments of the create function to fix this issue, as in...
let create i = Hashtbl.create i
In fact it should be noted that you only need to eta-expand one argument to remove the optional arguments from the inferred type signature as in...
let create ?random1 ?random2 x y z = Hashtbl.create (x+y+z);;
(* ?random1:'a -> ?random2:'b -> int -> int -> int -> ('c, 'd) Hashtbl.t *)
let create7 = create 7;;
(* create7 : int -> int -> ('_a, '_b) Hashtbl.t *)

Related

Unused variable vs let () and let _?

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.

What's meaning of this ocaml code segment?

I can't understand this ocaml code from ocaml compiler source code:
File: d:\src\ocaml-4.07.0\driver\pparse.ml
50: type 'a ast_kind =
51: | Structure : Parsetree.structure ast_kind
52: | Signature : Parsetree.signature ast_kind
there define a type ast_kind,define the type parameter 'a,but not use it?
I know the common use of type define like this:
type a=
|A of int
|B of int
so the
Structure : Parsetree.structure ast_kind
means what?the type of Structure is Parsetree.structure? or ast_kind?
I read the offical doc:
http://caml.inria.fr/pub/docs/manual-ocaml-312/manual016.html##manual.kwd53
it tell me only in the defination of record can use the ":"
type-representation ::= = constr-decl { | constr-decl }
∣ = { field-decl { ; field-decl } }
field-decl ::= field-name : poly-typexpr
∣ mutable field-name : poly-typexpr
so what's the meaning of this code segment?Thanks!
Starting from :
50: type 'a ast_kind =
51: | Structure : Parsetree.structure ast_kind
52: | Signature : Parsetree.signature ast_kind
This is read as follows :
line 50 : we define a parametrized type ast_kind whose parameter is 'a. The parameter is defined later in the lines 51 & 52.
On line 51 : the 'a parameter type is Parsetree.structure
And similarly for line 52.
Now, more generally, ast_kind is a GADT type (generalized algebraic datatypes), see GADT-manual and another example : Mads-hartmann.
Note that GADT has been introduced in Ocaml 4.00 - so the link you quote regarding documentation is outdated for that particular feature as it refers to Ocaml 3.12. You are currently inspecting the source code of Ocaml 4.07.

Use variant from dependency

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.

How to implement mixins in OCaml

How to implement mixins in the OCaml module system.
The closest I achieved is to use the following methodology, which I illustrate on a MixinFormat which adds usual output functions print, output and to_string on a mixin able to format.
Assume that we implement a module MixinFormat with the following signature:
module MixinFormat :
sig
(** Formatable mixin. *)
(** Input signature of the functor [MixinFormat.Make]. *)
module type Basis =
sig
type t
(** The type of formatted elements. *)
val format : Format.formatter -> t -> unit
(** [format fft a] pretty prints [a] on [fft]. *)
end
(** Output signature of the functor [MixinFormat.Make]. *)
module type Methods =
sig
type t
val to_string : t -> string
(** Convert to string. *)
val output : out_channel -> t -> unit
(** Output on the given output channel. *)
val print : t -> unit
(** Output on the standard output channel. *)
end
(** Functor implementing output mixins based on a format definition. *)
module Make(B:Basis): Methods
with type t := B.t
(** Signature of formatable mixins. *)
module type S =
sig
type t
include Basis with type t := t
include Methods with type t := t
end
end
We can now use it to add common output functions to a module able to format, as in:
module Date =
struct
module Prototype =
struct
type t = int * int * int
let format ppt (y,m,d) =
Format.fprintf ppt "%04d-%02d-%02d" y m d
end
include Prototype
include MixinFormat.Make(Prototype)
end
This works very well but has the convenient that it is not easily iterable: if a second mxin expects functions added to Prototype by MixinFormat.Make then we need to pack Prototype and MixinFormat.Make(Prototype) in Prototype2 which is a bit clumsy and hinders readability.
Is there an alternative implementation of mixins which could avoid to introduce a Prototype2 when iteratively using mixins?
Firstly, to avoid multiple definitions of the type t, your functor should probably be defined as:
module Make(B:Basis): Methods with type t := B.t
To avoid having to create inner modules, you can use recursive modules like this:
module rec Date : sig
type t = int * int * int
include Basis with type t := t
include Methods with type t := t
end = struct
type t = int * int * int
let format ppt (y,m,d) =
Format.fprintf ppt "%04d-%02d-%02d" y m d
include Make(Date)
end
However, it is worth noting that recursive modules can be a bit tricky. For example, if any of the values in your module (e.g. format) were not functions then this definition would not work.
It is also worth noting that OCaml's object system has excellent support for mixins. For examples, see Chapter 12 of Real World OCaml.

Ocaml: Error - this expression has type x but is used with type x

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
#