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

时间:2019-10-07 07:34:37

标签: set reason bucklescript

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

type fooVariant =
  | Foo
  | Bar
  | Baz;

我想要一个高效的,类型安全的,不变的集合。我认为Belt.Set听起来像我不想要的。但是,在我开始ReasonML学习时,我不能很快理解the Set documentation which is in BuckleScript format

一个简单的例子会让我快速而舒适地开始。 最好该示例包括以下项目:

  • 定义一种哈希集(例如type mySet = Set(fooVariant)
  • 初始化包含1个项目的集合(例如fooVariant.Foo
  • 添加新的内容(例如fooVariant.Bar
  • 测试集合中是否存在1个值(例如fooVariant.Foo

edit:我一开始在问题中有HashSet,但是后来我意识到它是可变的,而不是我不想要的。我不能完全确定“传送带”中的哪种类型最适合我的情况,但是让我们看看。

1 个答案:

答案 0 :(得分:2)

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时,the Reason playground可能会稍慢一些,并且会大大增加:

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

您可以在{{3}}上玩这两个游戏。

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

还请注意,尽管Pervasives.compare在此处方便地用作比较函数,并且可能已用于所有集合,从而似乎绕过了上面的问题,但它并不是一个完整的函数。例如,如果您尝试比较两个函数,它只会崩溃,而如果您尝试比较循环数据结构,它将不会终止。因此,有必要能够针对更复杂的类型使用自定义比较功能,并且是一个好主意。