Belt.Set
звучит так, как вы хотите. Он был разработан, чтобы быть быстрым и небольшим при компиляции в JavaScript, но я не совсем уверен, что он предназначен для использования людьми.
Вот пример, показывающий, как его можно использовать с вашим пользовательским типом.
// Create an "Id" module, to basically give the comparison function a type
module FooComparable =
Belt.Id.MakeComparable({
type t = fooVariant;
let cmp = Pervasives.compare;
});
// Define an alias for the set type
type fooSet = Belt.Set.t(fooVariant, FooComparable.identity);
// Initialize a set with one item
let s0 = Belt.Set.fromArray([|Foo|], ~id=(module FooComparable));
// Immutably add to the set
let s1 = Belt.Set.add(s0, Bar);
// Test for the presence of a value
Belt.Set.has(s1, Foo);
Сравните это со стандартной структурой данных , которая, вероятно, немного медленнее и значительно больше при компиляции в JavaScript:
// Create a specialized set module, again basically just to give the
// comparison function a type
module FooSet = Set.Make({
type t = fooVariant;
let compare = Pervasives.compare;
});
// Define an alias for the set type
type fooSet = FooSet.t;
// Initialize a set with one item
let s0 = FooSet.of_list([Foo]);
// Immutably add to the set
let s1 = FooSet.add(Bar, s0);
// Test for the presence of a value
FooSet.mem(Foo, s1);
Вы можете поиграть соба из них на игровой площадке Reason .
Как видно из примеров, оба из них требуют создания какого-то модуля вместо простой передачи функции сравнения непосредственно в созданиефункция. Это делается для того, чтобы одна и та же функция сравнения использовалась для всех операций в одном наборе. В противном случае, если, например, у вас есть два отдельных набора с одним и тем же типом, параметризованным только по типу, содержащемуся и инициализированным с помощью другой функции сравнения, не будет очевидно, каким должно быть объединение или пересечение двух наборов.
Также обратите внимание, что хотя Pervasives.compare
здесь удобно использовать в качестве функции сравнения, и, возможно, оно использовалось для всех наборов, что, по-видимому, обходило проблему, описанную выше, не является полной функцией. Например, если вы попытаетесь сравнить две функции, он просто потерпит крах, а если вы попытаетесь сравнить циклическую структуру данных, он не прекратит работу. Поэтому необходимо уметь использовать и неплохо использовать пользовательскую функцию сравнения для более сложных типов.