2009-09-20 10 views
16

Quiero usar OCaml para generar conjuntos de datos y hacer comparaciones entre ellos. He visto la documentación para tipos de Módulos como Set.OrderType, Set.Make, etc., pero no puedo encontrar la manera de inicializar un conjunto o utilizarlos de otra manera.OCaml: Establecer módulos

Respuesta

28

Los conjuntos se definen mediante una interfaz funcional. Para cualquier tipo dado, debe crear un módulo Set para ese tipo usando el functor Set.Make. Una desdichada supervisión de las bibliotecas estándar es que no definen instancias Set para los tipos incorporados. En la mayoría de los casos simples, es suficiente usar Pervasives.compare. He aquí una definición que sirva para int:

module IntSet = Set.Make( 
    struct 
    let compare = Pervasives.compare 
    type t = int 
    end) 

El módulo IntSet implementará la interfaz Set.S. Ahora se puede operar en conjuntos utilizando el módulo de IntSet:

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

Tenga en cuenta que no tiene que definir explícitamente la estructura de entrada para Set.Make como OrderedType; tipo de inferencia hará el trabajo por usted. Como alternativa, puede utilizar la siguiente definición:

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

module IntSet = Set.Make(IntOrder) 

Esto tiene la ventaja de que se puede volver a utilizar el mismo módulo para crear instancias de un Map:

module IntMap = Map.Make(IntOrder) 

Se pierde algo de generalidad en el uso de palabras funcionales, porque el tipo de los elementos es fijo. Por ejemplo, no podrá definir una función que tome un Set de algún tipo arbitrario y realice alguna operación en él. (Por suerte, el módulo Set sí declara muchas operaciones útiles en Set s.)

+1

"usted no será capaz de definir una función que toma un conjunto de algún tipo arbitrario" que podría, sin embargo, logre lo mismo definiendo la función dentro de un functor que tome su módulo Set específico como parámetro. pero para usarlo, por supuesto, el programador tendría que hacer otro módulo más con este functor, por lo que es menos conveniente – newacct

+0

Derecha. Son funtores hasta el final. –

9

Además de la respuesta de Chris, puede ser útil que decir que algunos módulos de la biblioteca estándar ya se adhieren a la firma OrderedType. Por ejemplo, puede simplemente hacer:

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 *) 

Y así sucesivamente.

Aquí hay un ejemplo de uso simple para StringSet; recuerde que los conjuntos son estructuras de datos funcionales, por lo que añadir un nuevo elemento a un conjunto devuelve un nuevo conjunto:

let set = List.fold_right StringSet.add ["foo";"bar";"baz"] StringSet.empty ;; 
StringSet.mem "bar" set ;; (* returns true *) 
StringSet.mem "zzz" set ;; (* returns false *)