2012-03-15 18 views
3

私は入力を制限したいintのセットを持っています。OCamlでのモジュール動作の変更

# RestrictedIntSet.add 15 (RestrictedIntSet.make 0 10) 
Exception: 15 out of acceptable range [0 .. 10] 

これを実装するにはどうすればよいですか。 Javaでは、それはのようなものになります:

Set<Integer> restrictedSet = new HashSet<Integer>() { 
    public boolean add(Integer i) { 
     if (i < lowerBound || i > upperBound) { 
      throw new IllegalArgumentException("out of bounds"); 
     } 
     return super.add(i); 
    } 

をまた、相続の少ない悪用する:

public class RestrictedSet { 

    private int lowerBound; 
    private int upperBound; 
    private Set elems = Sets.newHashSet(); 

    public RestrictedSet(int lowerBound, int upperBound) { 
     this.lowerBound = lowerBound; 
     this.upperBound = upperBound; 
    } 

    public boolean add(Integer i) { 
     if (i < lowerBound || i > upperBound) { 
     throw new IllegalArgumentException("out of bounds"); 
     } 
     return elems.add(i); 
    } 

    /* fill in other forwarded Set calls as needed */ 
} 

同等、OCamlの中でこれを行うための慣用的な方法は何ですか?

答えて

7

どのようなライブラリを使用していますかライブラリに依存していますか?標準ライブラリのSetモジュールを使用して

、あなたが次のことを行うことができます:

module type RestrictedOrderedType = sig 
    type t 
    val compare : t -> t -> int 
    val lower_bound : t 
    val upper_bound : t 
end 

module RestrictedSet (Elem : RestrictedOrderedType) = struct 
    include Set.Make(Elem) 

    exception Not_in_range of Elem.t 

    let check e = 
    if Elem.compare e Elem.lower_bound < 0 
    || Elem.compare e Elem.upper_bound > 0 
    then raise (Not_in_range e) 
    else e 

    (* redefine a new 'add' in term of the one in Set.Make(Elem) *) 
    let add e s = add (check e) s 

    let singleton e = singleton (check e) 
end 


(* test *) 
module MySet = RestrictedSet(struct 
    type t = int 
    let compare = compare 
    let lower_bound = 0 
    let upper_bound = 10 
end) 

let test1 = MySet.singleton 3 

let test2 = MySet.add (-3) test1 
(* Exception: Not_in_range (-3) *) 
2

私はgaschesの答え@好きです。

OCamlのSetモジュールは、OrderedTypeモジュールによってインスタンス化されるように設計されています。つまり、OCamlのネイティブintを直接使用することはできません。

したがって、要求された署名に従うモジュールを使用する必要があります。 gascheのRestrictedOrderedType署名の定義では、に下界と上限のフィールドがエレガントに含まれています。より粗いアプローチは、要求されたOrderedTypeシグニチャに準拠するOCamlのInt32またはInt64モジュールを使用し、MySetモジュールで境界をハードコードすることです。

以下は、この点を説明するためのガスチの例のわずかな再調整です。

module MySet = struct 
    include Set.Make(Int32) 

    exception Not_in_range of Int32.t 

    let lower_bound = Int32.of_int 5 

    let upper_bound = Int32.of_int 10 

    let add elt set = 
     if (elt < lower_bound)||(elt > upper_bound) 
     then raise (Not_in_range elt) 
     else add elt set 

    end;; 
関連する問題