OCaml:设置模块

时间:2009-09-20 22:43:50

标签: module set ocaml

我想使用OCaml生成数据集并在它们之间进行比较。我已经看过模块类型的文档,如Set.OrderTypeSet.Make等,但我无法弄清楚如何初始化集合或以其他方式使用它们。

2 个答案:

答案 0 :(得分:30)

使用functorial接口定义集合。对于任何给定类型,您必须使用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 )

这样做的好处是可以重复使用相同的模块来实例化Map

module IntMap = Map.Make( IntOrder )

你在使用仿函数时失去了一些通用性,因为元素的类型是固定的。例如,您将无法定义一个采用某种任意类型的Set并对其执行某些操作的函数。 (幸运的是,Set模块本身在Set上声明了许多有用的操作。)

答案 1 :(得分:12)

除了Chris的回答之外,说一些标准库模块已经遵守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 *)