Précédent   Forum du club des développeurs et IT Pro > Autres langages > Langages fonctionnels > F#
F# Forum d'entraide sur la programmation en langage fonctionnel F#
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 26/05/2008, 15h37   #1
gorgonite
Rédacteur/Modérateur

 
Avatar de gorgonite
 
Homme Nicolas Vallée
Ingénieur d'études
Inscription : décembre 2005
Messages : 9 962
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Vallée
Âge : 28
Localisation : France

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

Informations forums :
Inscription : décembre 2005
Messages : 9 962
Points : 18 154
Points : 18 154
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
gorgonite est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2008, 18h10   #2
SpiceGuid
Rédacteur
 
Avatar de SpiceGuid
 
Homme Damien Guichard
Inscription : juin 2007
Messages : 1 512
Détails du profil
Informations personnelles :
Nom : Homme Damien Guichard
Localisation : France, Loire (Rhône Alpes)

Informations forums :
Inscription : juin 2007
Messages : 1 512
Points : 2 495
Points : 2 495
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 projet, le blog dvp et le jeu vidéo.
Avant de poser une question je lis les règles du forum.
SpiceGuid est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2008, 19h52   #3
gorgonite
Rédacteur/Modérateur

 
Avatar de gorgonite
 
Homme Nicolas Vallée
Ingénieur d'études
Inscription : décembre 2005
Messages : 9 962
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Vallée
Âge : 28
Localisation : France

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

Informations forums :
Inscription : décembre 2005
Messages : 9 962
Points : 18 154
Points : 18 154
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
gorgonite est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2008, 21h23   #4
SpiceGuid
Rédacteur
 
Avatar de SpiceGuid
 
Homme Damien Guichard
Inscription : juin 2007
Messages : 1 512
Détails du profil
Informations personnelles :
Nom : Homme Damien Guichard
Localisation : France, Loire (Rhône Alpes)

Informations forums :
Inscription : juin 2007
Messages : 1 512
Points : 2 495
Points : 2 495
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 projet, le blog dvp et le jeu vidéo.
Avant de poser une question je lis les règles du forum.
SpiceGuid est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2008, 21h58   #5
gorgonite
Rédacteur/Modérateur

 
Avatar de gorgonite
 
Homme Nicolas Vallée
Ingénieur d'études
Inscription : décembre 2005
Messages : 9 962
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Vallée
Âge : 28
Localisation : France

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

Informations forums :
Inscription : décembre 2005
Messages : 9 962
Points : 18 154
Points : 18 154
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
gorgonite est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2008, 22h21   #6
gorgonite
Rédacteur/Modérateur

 
Avatar de gorgonite
 
Homme Nicolas Vallée
Ingénieur d'études
Inscription : décembre 2005
Messages : 9 962
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Vallée
Âge : 28
Localisation : France

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

Informations forums :
Inscription : décembre 2005
Messages : 9 962
Points : 18 154
Points : 18 154
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
gorgonite est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2008, 23h01   #7
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 962
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 962
Points : 1 148
Points : 1 148
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).
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2008, 23h20   #8
gorgonite
Rédacteur/Modérateur

 
Avatar de gorgonite
 
Homme Nicolas Vallée
Ingénieur d'études
Inscription : décembre 2005
Messages : 9 962
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Vallée
Âge : 28
Localisation : France

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

Informations forums :
Inscription : décembre 2005
Messages : 9 962
Points : 18 154
Points : 18 154
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
gorgonite est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2008, 10h32   #9
gorgonite
Rédacteur/Modérateur

 
Avatar de gorgonite
 
Homme Nicolas Vallée
Ingénieur d'études
Inscription : décembre 2005
Messages : 9 962
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Vallée
Âge : 28
Localisation : France

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

Informations forums :
Inscription : décembre 2005
Messages : 9 962
Points : 18 154
Points : 18 154
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
gorgonite est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2008, 16h07   #10
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 962
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 962
Points : 1 148
Points : 1 148
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.
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2008, 16h32   #11
gorgonite
Rédacteur/Modérateur

 
Avatar de gorgonite
 
Homme Nicolas Vallée
Ingénieur d'études
Inscription : décembre 2005
Messages : 9 962
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Vallée
Âge : 28
Localisation : France

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

Informations forums :
Inscription : décembre 2005
Messages : 9 962
Points : 18 154
Points : 18 154
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
gorgonite est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2008, 17h05   #12
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 962
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 962
Points : 1 148
Points : 1 148
Citation:
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...
LLB est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2008, 17h08   #13
gorgonite
Rédacteur/Modérateur

 
Avatar de gorgonite
 
Homme Nicolas Vallée
Ingénieur d'études
Inscription : décembre 2005
Messages : 9 962
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Vallée
Âge : 28
Localisation : France

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

Informations forums :
Inscription : décembre 2005
Messages : 9 962
Points : 18 154
Points : 18 154
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
gorgonite est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 16h26.


 
 
 
 
Partenaires

Hébergement Web