Reputation: 1559
Is there any difference between these two ?
I don't know which of them should I put in my .mli
file
module Comparable : sig
type t
val compare : t -> t-> int
end
module type Comparable = sig
type t
val compare : t -> t-> int
end
In real world ocaml
book, the authors say that the words interface, signature, module type can be used interchangeably.
PS:I would gladly change the question title to a better suited one, any proposals ?
Upvotes: 1
Views: 643
Reputation: 1418
module type Comparable = sig
type t
val compare : t -> t-> int
end
defines a module type. Inside an interface (e.g. a .mli
file), it is a promise that the implementation (the .ml
) contains the same module type definition.
module Comparable : sig
type t
val compare : t -> t-> int
end
in an interface is a promise to provide a module of that same type. It would be equivalent to
module Comparable : Comparable
(assuming the module type is indeed defined). It states that the corresponding .ml
contains a submodule named Comparable
.
Which of the two you should put in you .mli
depends on what promises you want to make. Both have their uses.
Module type definitions are commonly found in interfaces if they are needed as arguments to functors. Indeed your module type Comparable
is equal to Map.OrderedType
, the type of the argument of the functor Map.Make
.
One use case of submodules as above is to provide something that can be used as an argument to a functor. For example a .mli
could look like this:
type stuff = ...
val fancy : ... (* some operations on stuff *)
module Comparable : Comparable with type t=stuff
In this form it would make the type stuff
usable as the key type of a map.
That said, if your example is the complete real world example, then I suspect you want the module type definition, not the submodule: The submodule would not be very useful; you have no operation to construct anything of type t
.
Upvotes: 4
Reputation: 18912
Your first code fragment defines a module with a specific signature , the second one defines directly a signature not a module. To understand the difference, your code example may be rewriten to
module type COMPARABLE = sig
type t
val compare : t -> t-> int
end
module Comparable: COMPARABLE
Upvotes: 2
Reputation: 4441
.mli
file allows to constraint a .ml
file, see the example below :
/* foo.ml */
let foo1 x y = x + y
let foo = foo1
/* foo.mli */
val foo : int -> int -> int
/* main.ml */
open Foo
let r = foo 4 5
/* let r = foo1 4 5 ;; */
ocamlbuild main.native
will compile only when using foo
and will fail to compiler with foo1
.
Now, when you define a module, you can either hide some declaration when defining this module :
module Comparable : sig
/* the exposed interface */
end = struct
/* the computation */
end
Or, define a type for a module :
module type Comparable = sig
/* the exposed interface */
end
You will be able to use that type later in your code to constraint some module. With the example given above (!! delete the .mli file !!)
/* foo.ml */
let foo1 x y = x + y
let foo = foo1
/* main.ml */
module type T1 = sig
val foo : int -> int -> int
end
module F1 : T1 = Foo
let r = Foo.foo1 4 5
let r = F1.foo1 4 5 /* will fail because hiden by type T1 */
Upvotes: 1
Reputation: 66823
Say your file is named m.mli
. The first definition is what you use if your corresponding m.ml
file has a module Comparable
in it. The second is what you use to declare a module type (just the type of a module, not a module). In the first case, there is an actual compare
that can be called as M.Comparable.compare
. In the second case there's no compare function, just a type declaration.
It's not possible to know which is correct for you. They both make sense.
Upvotes: 1