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>
}