2009-09-20 10 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) 

モジュールIntSetSet.Sインタフェースを実装します。今、あなたはIntSetモジュール使用してセットを操作することができます:あなたが明示的にOrderedTypeとしてSet.Makeの入力構造を定義する必要はありません

let s = IntSet.empty ;; 
let t = IntSet.add 1 s ;; 
let u = IntSet.add 2 s ;; 
let tu = IntSet.union t u ;; 

注意を。型推論はあなたのために仕事をします。あなたはファンクタを使用して、いくつかの一般性を失うので、

module IntMap = Map.Make(IntOrder) 

module IntOrder : Set.OrderedType = struct 
    type t = int 
    let compare = Pervasives.compare 
end 

module IntSet = Set.Make(IntOrder) 

これは、あなたがMapをインスタンス化するために同じモジュールを再利用できるという利点があります。また、あなたは、次の定義を使用することができます要素の型は固定されています。たとえば、任意のタイプのSetを取り、その上で何らかの操作を実行する関数を定義することはできません。 (SetモジュールはSetで多くの便利な操作を宣言しています)

+1

"任意のタイプのセットを取る関数を定義することはできません"ただし、特定のSetモジュールをパラメータとするファンクタ内で関数を定義することで、同じことを達成できます。プログラマがこのファンクタを使用して別のモジュールを作成しなければならないので、あまり便利ではありません。 – newacct

+0

それは、ファンクターのすべての方法です。 –

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 *) 
関連する問題