如何在 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.
一个简单的示例可以让我快速而轻松地入门。
该示例最好包括以下项目:
- 定义一种哈希集(类似于
type mySet = Set(fooVariant)
)
- 用 1 个项目初始化集合(比如
fooVariant.Foo
)
- 通过添加(比如
fooVariant.Bar
)制作新集
- 测试集合是否存在 1 个值(比如
fooVariant.Foo
)
编辑:一开始我在问题中有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
在这里方便地用作比较函数,并且可能已用于所有集合,从而看似绕过了上述问题,但它并不是一个总函数。例如,如果您尝试比较两个函数,它只会崩溃,而如果您尝试比较循环数据结构,它不会终止。因此,有必要能够为更复杂的类型使用自定义比较函数,并且使用它是个好主意。
我有一个简单的变体。说:
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
)
编辑:一开始我在问题中有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
在这里方便地用作比较函数,并且可能已用于所有集合,从而看似绕过了上述问题,但它并不是一个总函数。例如,如果您尝试比较两个函数,它只会崩溃,而如果您尝试比较循环数据结构,它不会终止。因此,有必要能够为更复杂的类型使用自定义比较函数,并且使用它是个好主意。