如何在 ReasonML 中使用 Belt.Set 的示例?

An example of how to use Belt.Set in ReasonML?

我有一个简单的变体。说:

type fooVariant =
  | Foo
  | Bar
  | Baz;

我想要一个高效、类型安全、不可变的集合。我在想 Belt.Set 听起来像我不想要的。然而,在我 ReasonML 学习的开始阶段,我无法快速理解 the Set documentation which is in BuckleScript format.

一个简单的示例可以让我快速而轻松地入门。 该示例最好包括以下项目:

编辑:一开始我在问题中有HashSet,但后来我意识到它是可变的,而不是我想要的。我不确定腰带中的哪种类型最适合我的情况,但让我们看看。

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);

将其与 standard set data structure 进行比较,后者在编译为 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);

您可以在 the Reason playground.

上尝试这两个

从示例中可以看出,这两者都需要您创建某种模块,而不是将比较函数直接传递给创建函数。这是为了确保对同一集合的所有操作使用相同的比较函数。否则,例如,如果您有两个单独的集合,它们的类型相同,仅由包含的类型进行参数化,并使用不同的比较函数进行初始化,那么这两个集合的并集或交集应该是什么并不明显。

另请注意,虽然 Pervasives.compare 在这里方便地用作比较函数,并且可能已用于所有集合,从而看似绕过了上述问题,但它并不是一个总函数。例如,如果您尝试比较两个函数,它只会崩溃,而如果您尝试比较循环数据结构,它不会终止。因此,有必要能够为更复杂的类型使用自定义比较函数,并且使用它是个好主意。