You have received an answer to you question whether you can avoid explicitly naming the module returned by the Set.Make functor: not really.
However it is worth knowing why you are in this position with the Set module to begin with, and that is because of the universal quantification of type variables applied to value types in module signatures. Such type variables no longer mean "some type to be inferred by the compiler"; they stand instead for "for all types". In the associated implementation module(s), the function(s) or other value with the polymorphic signature must be implemented so that the relevant type variable(s) are capable of being any type.
Take a module for a set with a signature like the following, where the 'add' function calls up some internal comparison function in order to determine the ordering of elements:
sig
type 'a t
...
val empty : 'a t
val add : 'a t -> 'a -> 'a t
end
Such a signature is problematic because for the add function to be compilable under this signature, it must be polymorphic, which in turn means that the internal comparison function applied by it must also be polymorphic of type 'a -> 'a -> int. The standard library does indeed provide such a function in the form of the Stdlib.compare polymorphic structural comparison function, with some well-known downsides: namely, structural comparison is unreliable for complex data structures and cannot in practice be used to compare all things - for example, if you try to apply Stdlib.compare to a function you will get an exception. Accordingly it is generally better for the comparison function to be monomorphic - that is, you generally want different implementations of it for ints, floats, strings and so forth, or for entities of your own devising.
One way to achieve this, the one used by the standard library, is to make the element type monomorphic at the outset, so:
sig
type t
type elt
...
val empty : t
val add : t -> elt -> t
end
Now the internal comparison function can also be monomorphic, of type elt -> elt -> int. Such a module is most easily constructed using a functor applied to a struct which provides the element type and the comparison function. The type of the output module of the functor then bears a sharing constraint such as 'Set.S with type elt = [element type]': see the standard library's Set.Make functor for more.
One exception (an emergent property of ocaml's type system) to the rule about universal quantification mentioned above concerns higher order functions, in particular functions which take another function as an argument. Even though parameterised, such an argument may be passed a monomorphic function (provided in the case of a set that it matches the element type for which the set is constructed). So 'empty' could be turned into a function, possibly renaming it 'make' in consequence, which takes the comparison function as an argument and which stores the comparison function in a record or tuple for future use together with the root node of the set, resulting in a signature something like this:
sig
type 'a t
type 'a comp = 'a -> 'a -> int
...
val make : 'a comp -> 'a t
val add : 'a t -> 'a -> 'a t
end
However this runs up against a problem where a function takes more than one set as an argument, say in order to concatenate two sets. To work correctly it may be necessary that both sets have been constructed for the same comparison function. This requires parameterising the set with a second type parameter which holds some arbitrary phantom type representing the comparison function, which is somewhat tedious. That is in essence what the Jane Street Library's Base.Set module does.
In languages like C++ or Java, you can use generics to implement containers for the sub-set of types which have had, say, the Comparable interface or concept implemented for them. You cannot directly do that using type variables under ocaml's type system. Functors happen to be one of the more straightforward ways of achieving something similar, but it does have the somewhat verbose syntax to which you have referred.