IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

Module et interaction


Sujet :

Caml

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2009
    Messages : 53
    Points : 57
    Points
    57
    Par défaut Module et interaction
    Bonjour,

    Voilà j'essai de comprendre le système de module OCaml.
    Tout d'abord j'aimerai connaitre la différence entre
    module type E = sig .. end (peut-on écrire module type D = struct .. end)
    module E : sig .. end

    Pour le moment je souhaite juste compiler l'agencement des modules que j'ai déf.
    Assez simples (on passera les erreurs au niveau algorithmique j'ai écris vite sans tester):
    Le module Plus:
    Signature:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    module type Plus = 
    sig
      val mplus : int -> int -> int 
    end ;;
    Implémentation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    module Plus =
    struct
      let rec mplus m = function 
        | 0 -> m 
        | n -> 1 + mplus m (n - 1)
    end ;;
    Le module Fois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    module type Fois =  
    sig 
      val mfois: int -> int -> int 
    end ;;
    Implémentation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    module Fois = 
    struct
      let rec mfois n = function 
        | 0 -> 0
        | 1 -> n
        | x -> Plus.mplus n (mfois n (x-1))
    end;;
    Le module Exp :
    Signature
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    module type Exp = 
    sig 
      val mexp: int -> int -> int 
    end ;;
    Implémentation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    module Exp = 
    struct 
      let rec mexp n = function
        | 0 -> 1
        | 1 -> n
        | x -> Fois.mfois n (mexp n (x - 1))
    end;;
    Lorsque je défini les choses de cette façon la boucle d'interaction accepte bien le tout. Mais la compilation échoue

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    zuymanto$ ocamlc -c plus.ml
    File "plus.ml", line 1, characters 0-1:
    Error: The implementation plus.ml does not match the interface plus.cmi:
           The field `Plus' is required but not provided
    Lorsque je définie la signature de cette façon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    module Plus: 
    sig
      val mplus : int -> int -> int 
    end ;;
    Le module Plus compile mais les autres échouent module Plus inconnue ou Plus.mplus non reconnue.

    Il semblerait que quelque chose m'échappe. Je souhaite faire de la compilation de programme ocaml et non l'écrire dans la BI. Donc il faut absolument faire compiler et faire interagir mes modules à travers le processus de compilation.

    Merci d'avance.

  2. #2
    Membre actif
    Avatar de Ptival
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2004
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2004
    Messages : 70
    Points : 276
    Points
    276
    Par défaut
    Bonjour.

    Tout d'abord, je te conseille de te référer à la documentation concernant les modules et leur utilisation en compilation séparée :
    http://caml.inria.fr/pub/docs/manual...004.html#toc17
    Tu peux lire toute la page, pour également mieux comprendre les différences entre signatures et implémentations.

    Pour répondre à ta première sous-question :
    Tout d'abord j'aimerai connaitre la différence entre
    module type E = sig .. end (peut-on écrire module type D = struct .. end)
    module E : sig .. end
    module type SIGNATURE = sig ... end
    définit un "type de module" (plutôt appelé "signature" ou "interface")

    module IMPLEM : sig ...end = struct ... end
    définit un module IMPLEM, et vérifie qu'il suit bien la signature donnée après le ":"

    module type D = struct ... end
    est invalide : tu essaies de définir une signature comme étant égale à une implémentation !

    Par exemple, je peux écrire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    module type SIG = sig val x : int end;;
    (* définit la signature SIG comme synonyme de sig val x : int end *)
     
    module IMP = struct let x = 0 end;;
    (* définit un module IMP, sans restriction spéciale *)
     
    module IMP : SIG = struct let x = 0 end;;
    (* définit un module IMP, et vérifie qu'il satisfait la signature SIG *)
     
    module IMP : sig val x : int end = struct let x = 0 end;;
    (* définit un module IMP, et vérifie qu'il satisfait la signature anonyme qu'on a spécifié après ":" *)
     
    (* module IMP : SIG = struct let y = 0 end;; *)
    (* Mauvais : SIG attend un champ x : int qui n'est pas fourni dans l'implémentation d'IMP *)
     
    module IMP : SIG = struct let x = 0;; let y = 1;; end;;
    (* ok, IMP peut avoir plus de champs que ceux spécifiés par SIG *)
    Maintenant, pour revenir à ta question principale, je cite la documentation :

    In OCaml, compilation units are special cases of structures and signatures, and the relationship between the units can be explained easily in terms of the module system. A compilation unit A comprises two files:

    - the implementation file A.ml, which contains a sequence of definitions, analogous to the inside of a struct…end construct;

    - the interface file A.mli, which contains a sequence of specifications, analogous to the inside of a sig…end construct.
    Ainsi, tes fichiers devraient plutôt avoir la forme suivante :

    Plus.mli :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    val mplus : int -> int -> int
    Plus.ml :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    let rec mplus m = function 
        | 0 -> m
        | n -> 1 + mplus m (n - 1)
    etc.

    Implicitement, ton fichier Plus.mli est le corps d'une signature Plus, et ton fichier Plus.ml est le corps d'une implémentation de cette signature.

    J'espère ne pas avoir dit de bêtises, et que cela t'aide à mieux comprendre les différences entre signatures et implémentations (pense à la différence entre un type et une valeur, mais au niveau des modules, d'où "module type").

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Tout d'abord j'aimerai connaitre la différence entre
    module type E = sig .. end (peut-on écrire module type D = struct .. end)
    module E : sig .. end
    C'est simple, mais il faut bien comprendre. En OCaml tu as deux concepts différents :
    - les [italique]structures[/italique], qui décrivent l'implémentation d'un module, qui sont constituées d'une suite de "phrases de structure" (structure item) entourées par "struct ... end"; on parle parfois d'"expression de module"
    - les [italique]signatures[/italique], qui décrivent l'interface d'un module, qui sont constituées d'une suite de "phrases de signature" (signature item) entourées par "sig .. end"; on parle parfois de "type de module"

    `let plus x y = x + y` est une phrase de structure. `val plus : int -> int -> int` est une phrase de signature. `exception Foo of int` ou `type t` peuvent être utilisées à la fois comme phrase de structure ou phrase de signature.

    Il y a aussi des phrases qui servent à parler de sous-modules imbriqués (dans le module courant). Par exemple `module M = struct ... end` est une phrase de structure qui définit un module. Au contraire, `module M : sig ... end` est une phrase de signature qui définit un module (et donne sa signature). Enfin, `module type S = sig .. end` est à la fois une phrase de structure et une phrase de signature, qui décrit une signature (comme `type t = int`, qui définit un type, peut être utilisé dans une structure ou dans une signature).

    On peut donc écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    module Grand : sig
      module Petit : sig val plus : int -> int -> int end
    end = struct
      module Petit = struct let plus x y = x+y end
    end
    On a un module `Grand` dont on donne la signature et l'implémentation, qui décrivent un module imbriqué Petit contenant une opération plus.

    Le module Plus compile mais les autres échouent module Plus inconnue ou Plus.mplus non reconnue.
    Il y a une interaction en OCaml entre les modules et les fichiers qu'il faut bien comprendre. L'idée est assez simple: un fichier .ml, avec son .mli qui vient avec, définissent un module dont le nom est déterminé par le nom du fichier.

    Imagine que tu as un fichier "toto.ml" et son interface "toto.mli". "toto.ml" contient
    et "toto.mli" contient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    val plus : int -> int -> int
    Dans un autre fichier de code OCaml que tu écris, ou dans l'interpréteur interactif, tu peux parler de . En effet, si tu as bien compilé toto.ml et inclus le fichier objet résultant dans ton programme, c'est exactement équivalent à si tu avais écrit, quelque part dans ton programme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    module Toto =
    (struct
      let plus x y = x + y
    end : sig
      val plus : int -> int -> int
    end)
    Bref, un fichier .ml donne lieu à un module qui a le nom du fichier (avec une majuscule) et qui contient le contenu du fichier, directement. En particulier, si dans toto.ml tu as écris:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    module Plus = struct
      let plus x y = x+y
    end
    Alors dans ton fichier gabu.ml qui fparle de toto, il faut écrire `Toto.Plus.plus`, et non pas simplement `Plus.plus` ou `Toto.plus`, pour accéder à l'opération d'addition.

    Dans ton code les cas "| 1 -> ..." sont inutiles, ce sont des cas particuliers du cas général.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2009
    Messages : 53
    Points : 57
    Points
    57
    Par défaut
    Un grand merci à vous.
    Ptival merci d'avoir été aussi rapide clair et concis! Ca m'a permis de résoudre mon problème vite.
    Merci gasche pour ton explication détaillée cela ma permis de comprendre notamment le Toto.Plus.plus qui est en fait TRES important à comprendre en mon sens pour vraiment assimiler le tout.
    Le cas |1 c'est surtout pour ne pas refaire un appel rec quand on est à 1 "pseudo optimisation . Et le cas 0 vraiment si l'argument de base vaut 0. inutilement fait exprès donc.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2010] Interaction inexpliquée entre requête et module
    Par titi95 dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 27/02/2012, 15h22
  2. [Question] Interaction entre modules
    Par Deaf dans le forum JTheque
    Réponses: 3
    Dernier message: 01/02/2010, 12h27
  3. module Find
    Par martijan dans le forum Modules
    Réponses: 8
    Dernier message: 09/07/2003, 12h07
  4. cherche module ou langage pour récupérer des données audio..
    Par Ry_Yo dans le forum Langages de programmation
    Réponses: 5
    Dernier message: 12/05/2003, 18h44
  5. PerlDoc sur une fonction d'un module
    Par lesouriciergris dans le forum Modules
    Réponses: 2
    Dernier message: 13/03/2003, 21h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo