2009-09-20 91 views
16

我想使用OCaml生成數據集並在它們之間進行比較。我已經看到模塊類型的文檔,如Set.OrderType,Set.Make等,但我無法弄清楚如何初始化一套或以其他方式使用它們。OCaml:設置模塊

回答

28

集合使用函子接口定義。對於任何給定的類型,您必須使用Set.Make仿函數爲該類型創建一個Set模塊。對標準庫的一個不幸的疏漏是它們沒有爲內建類型定義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

「你不會是能夠定義一個函數,一些任意類型的集」你可以,然而,通過在函數中定義函數來完成同樣的事情,函數將您的特定Set模塊作爲參數。但是使用它當然程序員必須使用這個函數來創建另一個模塊,所以它不太方便 – newacct 2009-09-21 02:03:25

+0

沒錯。它一直是仿函數。 – 2009-09-21 03:42:51

9

除了克里斯的回答,可能是有用的說,一些標準庫模塊已經堅持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 *)