open Belt
module IntCmp = Belt.Id.MakeComparable({
type t = int
let cmp = (a, b) => Pervasives.compare(a, b)
})
module type EmptySet = {
type value
type identity
let empty: Set.t<value, identity>
}
module MakeEmptySet: EmptySet = {
type value = int
type identity = IntCmp.identity
- let empty = Set.Int.empty
+ let empty = Set.make(~id=module(IntCmp))
}

Even though your custom IntCmp module does the same thing that Belt.Set.Int does internally, it has a different identity type, so the two modules arenâ€™t interchangeable. Youâ€™ll always need to use your custom IntCmp module with the generic Belt.Set.

What youâ€™re doing is possible, but Iâ€™m not sure if itâ€™s necessary. Turning MakeEmptySet into functor seems redundant when the Belt.Id.MakeComparable functor should already do the work you need. You should just have to use Set.make(~id=module(MyCustomIntCmp)) to create a unique empty set.

A simpler pattern for making new types of sets is this:

open Belt
module IntCmp = Id.MakeComparable({
type t = int
let cmp = (a, b) => compare(a, b)
})
module AnotherIntCmp = Id.MakeComparable({
type t = int
let cmp = (a, b) => compare(b, a)
})
let emptySet = Set.make(~id=module(IntCmp))
let anotherEmptySet = Set.make(~id=module(AnotherIntCmp))

Part of the motivation behind using Belt.Id.MakeComparable is to avoid using â€śbigâ€ť functors, like the ones included in the OCaml stdlib (e.g. Set.Make), so you can just use the generic Belt.Set functions instead.

Hi JohnJ. This was exactly what I needed. The example a I gave in the playground is a much simplified of my actual application, which was essentially how to instantiate something looking like this:

module type AModuleType = {
type value
type identity
let aFunction: value => Map.t<value, int, identity>
}