我有一个简单的变体。说:
type fooVariant =
| Foo
| Bar
| Baz;
我想要一个高效的,类型安全的,不变的集合。我认为Belt.Set
听起来像我不想要的。但是,在我开始ReasonML学习时,我不能很快理解the Set documentation which is in BuckleScript format。
一个简单的例子会让我快速而舒适地开始。 最好该示例包括以下项目:
type mySet = Set(fooVariant)
)fooVariant.Foo
)fooVariant.Bar
)fooVariant.Foo
)edit:我一开始在问题中有HashSet,但是后来我意识到它是可变的,而不是我不想要的。我不能完全确定“传送带”中的哪种类型最适合我的情况,但是让我们看看。
答案 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
在此处方便地用作比较函数,并且可能已用于所有集合,从而似乎绕过了上面的问题,但它并不是一个完整的函数。例如,如果您尝试比较两个函数,它只会崩溃,而如果您尝试比较循环数据结构,它将不会终止。因此,有必要能够针对更复杂的类型使用自定义比较功能,并且是一个好主意。