user3131124
user3131124

Reputation: 119

ocaml: create set of polymorphic type

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

Answers (2)

didierc
didierc

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

Jeffrey Scofield
Jeffrey Scofield

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

Related Questions