2017-03-11 2 views
0

Y a-t-il une différence entre ces deux-là?Confusion sur la signature d'un module en Ocaml

Je ne sais pas lequel d'entre eux dois-je mettre dans mon dossier .mli

module Comparable : sig 
    type t 
    val compare : t -> t-> int 
end 

module type Comparable = sig 
    type t 
    val compare : t -> t-> int 
end 

Dans real world ocaml livre, les auteurs disent que les mots l'interface , la signature, le type de module peuvent être utilisés de manière interchangeable.

PS: Je serais heureux de changer le titre de la question pour un mieux adapté, des propositions?

Répondre

3
module type Comparable = sig 
    type t 
    val compare : t -> t-> int 
end 

définit un type de module. Dans une interface (par exemple un fichier .mli), il est promis que l'implémentation (.ml) contient la même définition de type de module.

module Comparable : sig 
    type t 
    val compare : t -> t-> int 
end 

dans une interface est une promesse de fournir un module de ce même type. Il serait équivalent à

module Comparable : Comparable 

(en supposant que le type de module est bien défini).Il indique que le .ml correspondant contient un sous-module nommé Comparable.

Lequel des deux que vous devriez mettre .mli dépend de ce que vous voulez faire. Les deux ont leurs utilisations.

Les définitions de type de module sont généralement trouvées dans les interfaces si elles sont nécessaires en tant qu'arguments aux foncteurs. En effet votre type de module Comparable est égal à Map.OrderedType, le type de l'argument du foncteur Map.Make.

Un cas d'utilisation des sous-modules comme ci-dessus est de fournir quelque chose qui peut être utilisé comme un argument à un foncteur. Par exemple, un .mli pourrait ressembler à ceci: Sous cette forme

type stuff = ... 
val fancy : ... (* some operations on stuff *) 

module Comparable : Comparable with type t=stuff 

il serait le type stuff utilisable comme le type de clé d'une carte. Cela dit, si votre exemple est l'exemple du monde réel complet, alors je suppose que vous voulez la définition du type de module, pas le sous-module: Le sous-module ne serait pas très utile; vous n'avez aucune opération pour construire quoi que ce soit de type t.

1

Supposons que votre fichier porte le nom m.mli. La première définition est ce que vous utilisez si votre fichier correspondant m.ml a un module Comparable dedans. La seconde est ce que vous utilisez pour déclarer un type de module (juste le type d'un module, pas un module). Dans le premier cas, il y a un compare qui peut être appelé M.Comparable.compare. Dans le second cas, il n'y a pas de fonction de comparaison, juste une déclaration de type.

Il n'est pas possible de savoir ce qui est correct pour vous. Ils ont tous deux un sens.

fichier
1

.mli permet de contraindre un fichier .ml, voir l'exemple ci-dessous:

/* foo.ml */ 
    let foo1 x y = x + y 
    let foo = foo1 

    /* foo.mli */ 
    val foo : int -> int -> int 

    /* main.ml */ 
    open Foo 
    let r = foo 4 5 
    /* let r = foo1 4 5 ;; */ 

ocamlbuild main.native recueille uniquement lors de l'utilisation foo et échouera au compilateur avec foo1.

Maintenant, lorsque vous définissez un module, vous pouvez cacher une déclaration lors de la définition de ce module:

module Comparable : sig 
    /* the exposed interface */ 
    end = struct 
    /* the computation */ 
    end 

Ou, définir un type pour un module:

module type Comparable = sig 
    /* the exposed interface */ 
    end 

Vous serez en mesure utiliser ce type plus tard dans votre code pour contraindre un module. Avec l'exemple donné ci-dessus (!! supprimer le fichier .mli !!)

/* foo.ml */ 
    let foo1 x y = x + y 
    let foo = foo1 

    /* main.ml */ 
    module type T1 = sig 
    val foo : int -> int -> int 
    end 

    module F1 : T1 = Foo 
    let r = Foo.foo1 4 5 
    let r = F1.foo1 4 5 /* will fail because hiden by type T1 */ 
2

Votre premier fragment de code définit un module avec une signature spécifique , le second définit directement une signature non un module. Pour comprendre la différence, votre exemple de code peut être à réécrit

module type COMPARABLE = sig 
    type t 
    val compare : t -> t-> int 
end 

module Comparable: COMPARABLE