2009-09-20 9 views
16

Je souhaite utiliser OCaml pour générer des ensembles de données et effectuer des comparaisons entre eux. J'ai vu la documentation pour les types de module comme Set.OrderType, Set.Make, etc, mais je ne peux pas comprendre comment initialiser un ensemble ou autrement les utiliser.OCaml: Définir les modules

Répondre

28

Les ensembles sont définis à l'aide d'une interface fonctoriale. Pour un type donné, vous devez créer un module Set pour ce type en utilisant le foncteur Set.Make. Un mauvais contrôle des bibliothèques standard est qu'elles ne définissent pas Set instances pour les types intégrés. Dans la plupart des cas, il suffit d'utiliser Pervasives.compare. Voici une définition qui fonctionne pour int:

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

Le module IntSet mettra en œuvre l'interface Set.S. Maintenant, vous pouvez utiliser sur les jeux utilisant le module IntSet:

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

Notez que vous ne devez pas définir explicitement la structure d'entrée pour Set.Make comme OrderedType; l'inférence de type fera le travail pour vous. Sinon, vous pouvez utiliser la définition suivante:

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

module IntSet = Set.Make(IntOrder) 

Ceci a l'avantage que vous pouvez réutiliser le même module pour instancier un Map:

module IntMap = Map.Make(IntOrder) 

Vous perdez généricité en utilisant foncteurs, parce que le type des éléments est fixe. Par exemple, vous ne serez pas en mesure de définir une fonction qui prend un Set de type arbitraire et effectue une opération dessus. (Heureusement, le module Set se déclare de nombreuses opérations utiles sur Set s.)

+1

« vous ne serez pas en mesure de définir une fonction qui prend un ensemble d'un certain type arbitraire » que vous pourriez, cependant, accomplissez la même chose en définissant la fonction à l'intérieur d'un foncteur qui prend en paramètre votre module Set spécifique. mais pour l'utiliser bien sur le programmeur devrait faire encore un autre module avec ce foncteur, donc c'est moins pratique – newacct

+0

. Ce sont des foncteurs tout le long. –

9

En plus de la réponse de Chris, il peut être utile de dire que certains modules de la bibliothèque standard adhèrent déjà à la signature OrderedType. Par exemple, vous pouvez simplement faire:

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

Et ainsi de suite.

Voici un exemple d'utilisation simple pour StringSet; rappelez-vous que les ensembles sont des structures de données fonctionnelles, afin d'ajouter un nouvel élément à un ensemble renvoie un nouvel ensemble:

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