Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 13 sur 13
  1. #1
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro Nicolas Vallée
    Ingénieur d'études
    Inscrit en
    décembre 2005
    Messages
    10 208
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas Vallée
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 208
    Points : 16 757
    Points
    16 757

    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 :
    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 :
    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
    Rédacteur
    Avatar de SpiceGuid
    Homme Profil pro Damien Guichard
    Inscrit en
    juin 2007
    Messages
    1 574
    Détails du profil
    Informations personnelles :
    Nom : Homme Damien Guichard
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : juin 2007
    Messages : 1 574
    Points : 2 449
    Points
    2 449

    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 :
    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: le cours OCaml, 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 Nicolas Vallée
    Ingénieur d'études
    Inscrit en
    décembre 2005
    Messages
    10 208
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas Vallée
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 208
    Points : 16 757
    Points
    16 757

    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 :
    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
    Rédacteur
    Avatar de SpiceGuid
    Homme Profil pro Damien Guichard
    Inscrit en
    juin 2007
    Messages
    1 574
    Détails du profil
    Informations personnelles :
    Nom : Homme Damien Guichard
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : juin 2007
    Messages : 1 574
    Points : 2 449
    Points
    2 449

    Par défaut

    Je ne saisi pas bien ton inquiétude.

    En OCaml tu écrirais:
    Code :
    1
    2
    3
    let H = HashTable.make n in
    H.add ...;
    H.find ...;
    En F# tu peux écrire:
    Code :
    1
    2
    3
    4
    let h = HashTable.make n in
    open HashTable;
    h.add ...;
    h.find ...;
    Du même auteur: le cours OCaml, 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 Nicolas Vallée
    Ingénieur d'études
    Inscrit en
    décembre 2005
    Messages
    10 208
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas Vallée
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 208
    Points : 16 757
    Points
    16 757

    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 :
    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 Nicolas Vallée
    Ingénieur d'études
    Inscrit en
    décembre 2005
    Messages
    10 208
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas Vallée
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 208
    Points : 16 757
    Points
    16 757

    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 Expert
    Inscrit en
    mars 2002
    Messages
    962
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 962
    Points : 1 128
    Points
    1 128

    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 :
    1
    2
    type Map with
      member m.foo = 42
    Tu peux passer par une classe abstraite :

    Code :
    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 Nicolas Vallée
    Ingénieur d'études
    Inscrit en
    décembre 2005
    Messages
    10 208
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas Vallée
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 208
    Points : 16 757
    Points
    16 757

    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 :
    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 :
    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 Nicolas Vallée
    Ingénieur d'études
    Inscrit en
    décembre 2005
    Messages
    10 208
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas Vallée
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 208
    Points : 16 757
    Points
    16 757

    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 :
    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 Expert
    Inscrit en
    mars 2002
    Messages
    962
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 962
    Points : 1 128
    Points
    1 128

    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 Nicolas Vallée
    Ingénieur d'études
    Inscrit en
    décembre 2005
    Messages
    10 208
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas Vallée
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 208
    Points : 16 757
    Points
    16 757

    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 Expert
    Inscrit en
    mars 2002
    Messages
    962
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 962
    Points : 1 128
    Points
    1 128

    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 Nicolas Vallée
    Ingénieur d'études
    Inscrit en
    décembre 2005
    Messages
    10 208
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas Vallée
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 208
    Points : 16 757
    Points
    16 757

    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.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •