我想使用 OCaml 生成数据集并在它们之间进行比较。我已经看过诸如Set.OrderType
、Set.Make
等模块类型的文档,但我不知道如何初始化一个集合或以其他方式使用它们。
问问题
13694 次
2 回答
32
集合是使用函数接口定义的。对于任何给定的类型,您必须使用函子Set
为该类型创建一个模块。Set.Make
对标准库的一个不幸的疏忽是它们没有Set
为内置类型定义实例。在大多数简单的情况下,使用Pervasives.compare
. 这是一个适用于的定义int
:
module IntSet = Set.Make(
struct
let compare = Pervasives.compare
type t = int
end )
该模块IntSet
将实现Set.S
接口。现在您可以使用该IntSet
模块对集合进行操作:
let s = IntSet.empty ;;
let t = IntSet.add 1 s ;;
let u = IntSet.add 2 s ;;
let tu = IntSet.union t u ;;
请注意,您不必将输入结构显式定义Set.Make
为OrderedType
; 类型推断将为您完成工作。或者,您可以使用以下定义:
module IntOrder : Set.OrderedType = struct
type t = int
let compare = Pervasives.compare
end
module IntSet = Set.Make( IntOrder )
这样做的好处是您可以重复使用相同的模块来实例化 a Map
:
module IntMap = Map.Make( IntOrder )
你在使用仿函数时失去了一些通用性,因为元素的类型是固定的。例如,您将无法定义一个采用Set
某种任意类型并对其执行某些操作的函数。(幸运的是,Set
模块本身在 s 上声明了许多有用的操作Set
。)
于 2009-09-20T23:25:33.250 回答
12
除了克里斯的回答之外,说一些标准库模块已经遵守OrderedType
签名可能很有用。例如,您可以简单地执行以下操作:
module StringSet = Set.Make(String) ;; (* sets of strings *)
module Int64Set = Set.Make(Int64) ;; (* sets of int64s *)
module StringSetSet = Set.Make(StringSet) ;; (* sets of sets of strings *)
等等。
这是一个简单的用法示例StringSet
;请记住,集合是函数式数据结构,因此向集合添加新元素会返回一个新集合:
let set = List.fold_right StringSet.add ["foo";"bar";"baz"] StringSet.empty ;;
StringSet.mem "bar" set ;; (* returns true *)
StringSet.mem "zzz" set ;; (* returns false *)
于 2009-09-21T14:35:04.877 回答