Using a Set in a module type

Suppose I have a module module Bounded(E: Set.OrderedType), and I want to use
Set.Make(E) as a component of Bounded.t, like

type t = { mutable data : Set.Make(struct
    type t = E.t let compare = compare end); };

Is there a way to do that?

Directly, no: the way to do this is to name a module that is the result of the functor application. Like this:

module ESet = Set.Make (E)

type t = {
  mutable data : ESet.t;
}

And if you need to write the signature of that module:

module ESet : Set.S with type elt = E.t

type t = {
  mutable data : ESet.t;
}

Note that functor application is side effecting and allowing it in type definitions would cause all kinds of problems.

Thanks, @gsg. I was a bit unclear. My problem is creating ESet within another functor. E.g., I would like to do something like this, but syntactically valid:

module Bounded(E: Set.OrderedType) = struct

  let module SE = Set.Make(struct
      type t = E.t let compare = E.compare end)

  type t = {
    bound : int ;
    mutable data : SE.t;
  }
...

It’s very much the same for functors:

module Bounded (E: Set.OrderedType) = struct
  module SE = Set.Make (E)

  type t = {
    bound : int ;
    mutable data : SE.t;
  }
end

A few things to note: let module M = ... is the syntax for local binding of modules. module M = ... defines an element within the current module, which is what you want here.

You can just pass E to Set.Make because module type checking is structural: if E has fields of the right names with the right types, it will be accepted. (They can be out of order, there can be other fields, etc - all of that will be ignored.)

1 Like

To be pedant, it is in fact possible to access type components of a functor application inside a type definition. For instance,

type t = { x : Set.Make(String).t }

is valid. It is indeed generally better to name the result of the functor application before using it, but this is not always easy when recursive modules are involved.

1 Like

Thanks, gsg. That worked.