Пример использования Belt.Set в ReasonML? - PullRequest
1 голос
/ 07 октября 2019

У меня есть простой вариант. скажем:

type fooVariant =
  | Foo
  | Bar
  | Baz;

И я хочу эффективный, безопасный тип, неизменный набор. Я думаю, что Belt.Set звучит так, как будто я не хочу. Тем не менее, находясь в начале обучения ReasonML, я не могу быстро понять документацию Set в формате BuckleScript .

Простой пример поможет мне начать быстро и с комфортом. Предпочтительно, чтобы пример включал в себя следующие элементы:

  • определяет тип хеш-набора (например, type mySet = Set(fooVariant))
  • Инициализирует набор с 1 элементом (скажем, fooVariant.Foo)
  • Создать новый набор с добавлением (скажем, fooVariant.Bar)
  • Проверить набор на наличие 1 значения (скажем, fooVariant.Foo)

редактировать: у меня был HashSetв начале вопроса, но потом я понял, что это изменчиво, а не то, что я не хочу. Я не совсем уверен, какой из типов в Поясе лучше всего подходит для моей ситуации, но давайте посмотрим.

1 Ответ

2 голосов
/ 07 октября 2019

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 здесь удобно использовать в качестве функции сравнения, и, возможно, оно использовалось для всех наборов, что, по-видимому, обходило проблему, описанную выше, не является полной функцией. Например, если вы попытаетесь сравнить две функции, он просто потерпит крах, а если вы попытаетесь сравнить циклическую структуру данных, он не прекратит работу. Поэтому необходимо уметь использовать и неплохо использовать пользовательскую функцию сравнения для более сложных типов.

...