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

F# Discussion :

paramétrer un module par un autre module


Sujet :

F#

  1. #1
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut paramétrer un module par un autre module
    Salut,


    J'ai signalé dans un post précédent que je chercherais à paramétrer un module (environment) par un autre module (structure interne quelconque ayant une interface à la Hashtbl)


    je suis parti sur la création d'une classe avec des méthodes statiques que je devrais surcharger.

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #light
    #nowarn "62"
    
    /// static type to represent any Hashtab-like type
    type ('a,'b) IHashtab() =
       static member create (i : int) : ('a,'b) IHashtab = IHashtab<'a,'b>()
       static member add  (m : ('a,'b) IHashtab) (key:'a) (value:'b) : unit = raise Not_found
       static member replace (m : ('a,'b) IHashtab) (key:'a) (value:'b) : unit = raise Not_found
       static member find (m : ('a,'b) IHashtab) (key:'a) : 'b = raise Not_found
       static member iter (f : 'a -> 'b -> unit) (m : ('a,'b) IHashtab) : unit = ()
       static member remove (m : ('a,'b) IHashtab) (key:'a) : unit = raise Not_found
    
    exception Not_found
    
    /////////////////////
    
    open Ihashtab
    open System.Reflection
    type environment = IHashtab<string,valeur>
    
    type 'a Environment() =
        inherit IHashtab<string,valeur>()
        static member create i : environment = 
           let typeA = typeof<'a>
           let methodA = typeA.GetMethod("create")
           methodA.Invoke(null,[|i|])
    
    (*
        static member find (env : environment) (v : string) : valeur = 'a.find env v
        static member iter f (env : environment) = 'a.iter f env
        static member add (env : environment) v val_expr = 'a.add env v val_expr
        static member replace (env : environment) v val_expr = 'a.replace env v val_expr
        static member assign (env : environment) (v : string) (val_expr : valeur) =
          try 
            let _ = find env v
            replace env v val_expr 
          with Not_found -> 
            add env v val_expr 
    *)
    Ensuite, il suffit de jouer avec l'introspection pour invoquer les méthodes, et de caster le résultat...

    mais pour le moment, impossible de caster ^^
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Error	1	Type constraint mismatch. The type   obj is not compatibile with type  environment.

    ça me semble être une bonne approche pour garder l'aspect "module"

    qu'en dites-vous ?
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  2. #2
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut
    En fait c'est juste un type polymorphe.
    Tu peux créer autant de fonctions make/create que tu veux qui implémenteront chacune un ('a,'b) hash_table.

    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
    19
    20
    21
    22
    23
    24
    25
    26
    module HashTable = struct
    
    type ('a,'b) t =
      {
      add: 'a -> 'b -> unit;
      replace: 'a -> 'b -> unit;
      find: 'a -> 'b;
      remove: 'a -> unit;
      }
    
    let make i =
      let mes_champ_privés = ... in
      let add k v = ...
      and replace k v = ... 
      and find k = ...
      and remove k = ...
      in
      {
      add = add;
      replace = replace;
      find = find;
      remove = remove;
      }
    
    end
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  3. #3
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    mais ensuite comment être sûr de pouvoir utiliser un seul module d'abstraction pour accéder à tout ?

    parce que dans ce style, j'avais pensé à cela... mais ça ne me plaît pas trop

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    #light
    #nowarn "62"
     
    /// static type to represent any Hashtab-like type
    type ('a,'b) IHashtab =
     interface
       abstract member add  : 'a -> 'b -> unit
       abstract member replace : 'a -> 'b -> unit
       abstract member find : 'a -> 'b
       abstract member iter : ('a -> 'b -> unit) -> unit
       abstract member remove : 'a -> unit
     end
     
    exception Not_found
     
    //////////////////
     
    open Ihashtab
    type environment<'value> (i : int) =
      let hashtab = Hashtbl.create i
     
      interface IHashtab<string,'value> with
        member self.add  key value =
          Hashtbl.add hashtab key value
     
        member self.replace key value =
          Hashtbl.replace hashtab key value
     
        member self.remove key =
          Hashtbl.remove hashtab key
     
        member self.find key =
          Hashtbl.find hashtab key
     
        member self.iter f =
          Hashtbl.iter f hashtab
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  4. #4
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut
    Je ne saisi pas bien ton inquiétude.

    En OCaml tu écrirais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let H = HashTable.make n in
    H.add ...;
    H.find ...;
    En F# tu peux écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let h = HashTable.make n in
    open HashTable;
    h.add ...;
    h.find ...;
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  5. #5
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    avec le second code, et ce module environment, j'arrive à avoir quelque chose de correct tout est abstrait par IHashtab<string,valeur>

    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
    19
    20
    21
    22
    23
    24
    25
    26
    /// environment can be seen as a set of (name,value)
    module Environment =
      /// Creates a new environment
      let create i = environment(i) :> IHashtab<string,valeur> 
      /// Adds a variable in the environment, and assigns it the given value
      let add (env:IHashtab<string,valeur>) key value =
         env.add key value
      /// Replaces the value of a variable
      let replace (env:IHashtab<string,valeur>) key value =
         env.replace key value
      /// Removes the entry corresponding to a variable
      let remove (env:IHashtab<string,valeur>) key =
         env.remove key
      /// Finds the value of a variable
      let find (env:IHashtab<string,valeur>) key =
         env.find key
      /// Iterates a function on all the elements
      let iter f (env:IHashtab<string,valeur>) =
         env.iter f
      /// Tries to replace value, but if it doesn't exist, it creates it
      let assign (env:IHashtab<string,valeur>) key value = 
         try 
           let _ = find env key
           replace env key value 
         with Not_found -> 
           add env key value

    en revanche, F# ne me laisse pas paramétrer mon module Environment par 'valeur afin de pouvoir utiliser une class environment<'valeur>
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  6. #6
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    bizarre, ça ne remplit pas ma hashtab
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  7. #7
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    J'ai du mal à comprendre ce que tu veux exactement, au final.


    Citation Envoyé par gorgonite Voir le message
    mais pour le moment, impossible de caster ^^
    Essaie avec unbox.

    Mais cette approche n'est pas bonne (elle est dangereuse).



    Sinon, pour ajouter des méthodes à un type, tu as les extensions de méthodes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    type Map with
      member m.foo = 42
    Tu peux passer par une classe abstraite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    type Hash() =
      abstract member Add: int -> int -> unit
      default h.Add x y = not_found()
     
    let make = {new Hash() with member h.Add x y = printfn "%d,%d" x y }
    Tu peux aussi passer par une interface (IDictionary existe déjà). Éventuellement, tu peux survoler le fichier collections.fs pour avoir un exemple (par exemple, le type Map implémente l'interface IDictionary).

  8. #8
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par LLB Voir le message
    J'ai du mal à comprendre ce que tu veux exactement, au final.

    je joue... je veux surtout voir ce qu'il diffère (modules paramétrés en OCaml, mais pas en F#)

    pour le moment, je ne suis pas sur quelque chose de trop sérieux... tant que tu ne me voies pas parler de quelque chose en rapport avec le forme SSA, je suis sur un modèle de test


    Citation Envoyé par LLB Voir le message
    Tu peux aussi passer par une interface (IDictionary existe déjà). Éventuellement, tu peux survoler le fichier collections.fs pour avoir un exemple (par exemple, le type Map implémente l'interface IDictionary).

    je vais tenter... mais ça risque de m'obliger à définir plus de méthodes que je n'en ai réellement besoin



    sinon comprends-tu pourquoi rien ne semble remplir ma hashtab avec l'interface IHashtab et la classe environment

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    #if TRY_PARAMETRIC_ENV
     
    open Ihashtab
    type environment (i : int) =
      let mutable hashtab = Hashtbl.create i
     
      interface IHashtab<string,valeur> with
        member self.add  key value =
          Hashtbl.add hashtab key value
     
        member self.replace key value =
          Hashtbl.replace hashtab key value
     
        member self.remove key =
          Hashtbl.remove hashtab key
     
        member self.find key =
          Hashtbl.find hashtab key
     
        member self.iter f =
          Hashtbl.iter f hashtab
     
    /// environment can be seen as a set of (name,value)
    module Environment =
      /// Creates a new environment
      let create i = environment(i) :> IHashtab<string,valeur> 
      /// Adds a variable in the environment, and assigns it the given value
      let add (env:IHashtab<string,valeur>) key value =
         env.add key value
      /// Replaces the value of a variable
      let replace (env:IHashtab<string,valeur>) key value =
         env.replace key value
      /// Removes the entry corresponding to a variable
      let remove (env:IHashtab<string,valeur>) key =
         env.remove key
      /// Finds the value of a variable
      let find (env:IHashtab<string,valeur>) key =
         env.find key
      /// Iterates a function on all the elements
      let iter f (env:IHashtab<string,valeur>) =
         env.iter f
      /// Tries to replace value, but if it doesn't exist, it creates it
      let assign (env:IHashtab<string,valeur>) key value = 
         try 
           let _ = find env key
           replace env key value 
         with Not_found -> 
           add env key value
     
    #else
     
    type environment = (string,valeur) Myhashtab.t //Hashtbl.t
     
    /// environment can be seen as a set of (name,value)
    module Environment =
        /// Creates a new environment
        let create i : environment = Myhashtab.create i
        /// Finds the value of a variable
        let find (env : environment) key : valeur = Myhashtab.find env key
        /// Iterates a function on all the elements
        let iter f (env : environment) = Myhashtab.iter f env
        /// Adds a variable in the environment, and assigns it the given value
        let add (env : environment) key value = Myhashtab.add env key value
        /// Replaces the value of a variable
        let replace (env : environment) key value = Myhashtab.replace env key value
     
        /// Tries to replace value, but if it doesn't exist, it creates it
        let assign (env : environment) key value =
          try 
            let _ = find env key
            replace env key value 
          with Not_found -> 
            add env key value 
     
    #endif

    en gros, ça passe sans TRY_PARAMETRIC_ENV, mais pas avec



    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
     
    gorgonite@GorgonMobile:~/Bureau/these/projets/fsharp-pseudo_pascal$ make test
    /usr/bin/mono --runtime=v2.0.50727  compilo.exe --show-ast --int --analyze ./test.code
    [Declare ["x"]; Assign (Var "x",Intconst 1);
     While
      (Test ("<>",[Var "x"; Intconst 5000]),
       [Assign (Var "x",Operateur ("+",[Var "x"; Intconst 1]))])]
     
     
    Unhandled Exception: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
      at Microsoft.FSharp.Collections.HashTableOps.chainFind[String,valeur] (IEqualityComparer`1 ops, System.String x, Microsoft.FSharp.Collections.HashChain`2 _arg1) [0x00000] 
      at Microsoft.FSharp.Collections.HashTableOps.find[String,valeur] (Microsoft.FSharp.Collections.HashMultiMap`2 t, System.String x) [0x00000] 
      at Microsoft.FSharp.Collections.HashMultiMap`2[System.String,Types+valeur].get_Item (System.String ) [0x00000] 
      at Types+Environment.assign (IHashtab`2 env, System.String key, .valeur value) [0x00000] 
    make: *** [test] Erreur 1
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  9. #9
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par gorgonite Voir le message
    sinon comprends-tu pourquoi rien ne semble remplir ma hashtab avec l'interface IHashtab et la classe environment
    ben voilà, j'utilisais des assign pour remplir, mais à la première assignation, il fait un add et non un replace.

    donc KeyNotFoundException est levée... il faut alors préciser que Not_found est justement un alias pour cette exception

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    exception Not_found = System.Collections.Generic.KeyNotFoundException

    le hic est que cela marchait bien avec le module Hashtbl de la librairie de base, ont-ils fait cette "magouille" aussi ?
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  10. #10
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    Utilise la fonction "not_found()", plutôt que de redéfinir ton exception. Les exceptions sont parfois mappées aux types .Net, justement pour améliorer l'interopérabilité.

    Évite d'utiliser des exceptions pour les cas "normaux". Ici, tryfind + pattern matching est largement préférable.


    Mais a priori, c'est la solution de la classe abstraite qui correspond le mieux à tes besoins.

  11. #11
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par LLB Voir le message
    Utilise la fonction "not_found()", plutôt que de redéfinir ton exception. Les exceptions sont parfois mappées aux types .Net, justement pour améliorer l'interopérabilité.

    mais je ne lève pas d'exception ici... je voulais juste la récupérer
    je vais regarder de plus près

    Citation Envoyé par LLB Voir le message
    Évite d'utiliser des exceptions pour les cas "normaux". Ici, tryfind + pattern matching est largement préférable.

    EDIT : arf, bien sûr IHashtab<'key,'value>.tryfind : 'key -> option<'value>

    fait

    Citation Envoyé par LLB Voir le message
    Mais a priori, c'est la solution de la classe abstraite qui correspond le mieux à tes besoins.
    effectivement, mais je trouve dommage de ne pas pouvoir paraméter mon module par un type, et ainsi garder environment<'valeur> et Environment<'environment>
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  12. #12
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    mais je ne lève pas d'exception ici... je voulais juste la récupérer
    Tu ne l'as pas déclaré avant ?

    Si tu utilises l'exception Not_found, tu devrais avoir un warning (compatibilité Caml). Sauf si tu l'as redéfini...

  13. #13
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par LLB Voir le message
    Tu ne l'as pas déclaré avant ?

    Si tu utilises l'exception Not_found, tu devrais avoir un warning (compatibilité Caml). Sauf si tu l'as redéfini...
    j'ai du la déclarer dans ihashtab.fs

    sinon j'ai fait un nowarn 62
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

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

Discussions similaires

  1. [V7] Modifier une vue de base déjà modifiée par un autre module
    Par alexdess dans le forum Odoo (ex-OpenERP)
    Réponses: 9
    Dernier message: 05/12/2018, 13h51
  2. Cacher un champ développé par un autre module.
    Par alexdess dans le forum Odoo (ex-OpenERP)
    Réponses: 17
    Dernier message: 15/07/2014, 17h28
  3. Réponses: 5
    Dernier message: 19/10/2011, 18h05
  4. Executer la procedure d un module depuis un autre module
    Par sebastien_oasis dans le forum VBA Access
    Réponses: 2
    Dernier message: 03/08/2007, 12h08
  5. Réponses: 4
    Dernier message: 14/05/2007, 14h44

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