質問
私はOCamlは、データのセットを生成するために使用し、それらの間の比較をしたいです。私はなどSet.OrderType
、Set.Make
、のようなモジュールの種類のドキュメントを見てきましたが、私はセットを初期化するか、そうでない場合は、それらを使用する方法を見つけ出すことはできません。
解決
セットは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
sに多くの有用な操作を宣言する。)
他のヒント
クリスの答えに加えて、いくつかの標準ライブラリモジュールが既に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 *)