Reputation: 119
In a module, I have defined a type that represents a graph node, which has a polymorphic data field i.e.
type 'a t = {data: 'a; adj: 'a t list}
How can I go about creating a Set of this data? I have tried the following (as per one of the suggestions here.
let cmp (g1:int Graph.t) (g2: int Graph.t) : int=
if phys_equal g1 g2 then
0
else
Int.compare g1.data g2.data
let make_set () =
let module Ord=struct
type t=int Graph.t
let compare=cmp
end
in (module Set.Make(Ord): Set.S with type elt=Ord.t)
But when I do, I get "The signature constrained by `with' has no component named elt"
Upvotes: 0
Views: 555
Reputation: 14730
That code works fine in the interpreter for me. Perhaps you've opened a different Set
module without the elt
type defined in S
?
If I define the following Set
in the interpreter:
# module Set = struct
module type S = sig end
end;;
module Set : sig module type S = sig end end
And then simply redefine make_set
as you wrote it, I actually get the same error message. When trying out code with the interpreter, always keep in mind that you may be working with definitions you wrote previously.
As a rule of thumb, try to avoid binding values to names already in use in the libraries you wish to employ (I know it's tempting to shorten your names there, but at least add them a small distinctive prefix - for instance use ISet
instead of Set
in your case).
you can always run your code as a script, i.e. by launching it from the command line as follow:
$ ocaml my_script.ml
Or by the #use
directive at the interpreter prompt. This let you write code snippets before testing them out with a fresh ocaml environment.
Finally, as in @Jeffrey's provided answer, an unpacked module is good enough for most purpose; your code was about instantiating a first class module, which is only interesting if you intend to pass that module around without the use of functors. See the documentation on modules (and related extensions of the language) for further explanation.
Upvotes: 1
Reputation: 66808
I'm not sure exactly what you're trying to do, but if you just want to make sets of nodes whose data type is int
, you don't need to use anything fancier than the usual OCaml module operations.
The following code works for me:
module Graph =
struct
type 'a t = {data: 'a; adj: 'a t list}
end
let cmp (g1:int Graph.t) (g2: int Graph.t) : int =
if g1 == g2 then
0
else
compare g1.Graph.data g2.Graph.data
module GSet = Set.Make(struct type t = int Graph.t let compare = cmp end)
Here's a session with the code:
$ ocaml
OCaml version 4.01.0
# #use "g.ml";;
module Graph : sig type 'a t = { data : 'a; adj : 'a t list; } end
val cmp : int Graph.t -> int Graph.t -> int = <fun>
module GSet :
sig
type elt = int Graph.t
. . .
end
# let myset = GSet.add { Graph.data = 14; adj = [] } GSet.empty;;
val myset : GSet.t = <abstr>
# GSet.is_empty myset;;
- : bool = false
I don't see a reason to constrain the module type, as Set.S
is already the module type returned by Set.Make
. But I am not a sophisticated user of OCaml module types.
Upvotes: 1