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 :

[Ocaml] typage de fonctions polymorphes et portée de typage


Sujet :

Caml

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut [Ocaml] typage de fonctions polymorphes et portée de typage
    Bonjour,

    Je suis confronté à un problème. Je dois extraire le type d'une fonction polymorphe afin de pouvoir typer l'un des champs d'une structure. Supposons par exemple que j'ai la fonction polymorphe suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    val compare : 'a -> 'a -> bool
    Si je souhaite extraire son type, il me semble que je dois procéder ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    type 'a t = 'a -> 'a -> bool
     
    val compare : 'a t
    Maintenant, j'ai la construction suivante :

    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
    let compare x y = (x = y)
     
    module type S =
    sig
      type t
      val x : t
    end
     
    let _ =
      let g : 'a t = compare in
      let module M (A : S) =
        struct
          let y = g A.x A.x
        end
      in
        ()
    ;;
    me produisant l'erreur suivante :

    File "test.ml", line 16, characters 16-19:
    This expression has type A.t but is here used with type 'a
    The type constructor A.t would escape its scope
    L'erreur pointe sur l'utilisation de A.x. Si je ne force pas g à être de type 'a t, alors je n'ai pas d'erreur. Oui, mais j'ai besoin de la typer puisque dans le programme original c'est un champ de structure. Comment contourner le problème ?

  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
    Ton type A.t est monomorphe tandis que ton type 'a t est polymorphe.

    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    module type S =
    sig
      type 'a t = 'a -> 'a -> bool
      val compare : 'a t
    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
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Certes. Mais les deux types n'ont rien à voir. Appelle les t1 et t2 si tu veux.

  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
    Et comme ceci, ça ferait l'affaire ?

    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    let _ =
      let module M (A : S) =
        struct
          let y = compare A.x A.x
        end
      in
      let g : 'a t = compare in ()
    ;;
    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
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Je répète, le but est de référencer une fonction, pas de résoudre les liens à la main : il s'agit d'utiliser de la liaison dynamique.

  6. #6
    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
    La raison de ton problème est un peu subtile. Elle ne vient pas directement de l'utilisation de ta valeur `g`.
    Je pense qu'elle vient précisément de la présence de la variable d'inférence `'a`.
    En effet, quand tu mets la variable d'inférence, tu donnes un nom, hors du module M, au type de A.x. Accepter cette unification c'est accepter que le type de A.x s'échappe par la variable 'a, et OCaml le refuse.

    Tu peux contourner le problème avec un vrai type polymorphe (qui contient un quantificateur universel), accessible en Caml uniquement dans les champs structures et objets :

    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
    type 'a t = 'a -> 'a -> bool
    let compare x y = (x = y)
     
    (* version polymorphe *)
    type poly_t = { f : 'a . 'a t }
    let compare_poly = { f = compare }
     
    module type S =
    sig
      type t
      val x : t
    end
     
    let _ =
      let g : poly_t = compare_poly in
      let module M (A : S) =
        struct
          let y = g.f A.x A.x
        end
      in
        ()
    Dans ce cas, poly_t ne laisse plus s'échapper de variable d'inférence, et la dernière phrase est correcte.

    Les restrictions aux structures et objets du polymorphisme d'ordre supérieur de Caml le rend un peu lourd à utiliser. Si ton type polymorphe est déjà le composant d'une structure, c'est très bien, puisque ça te fait une couche de moins.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    Ah parfait ! Merci.

    J'avais cherché comment quantifier et j'ai du rater la différence entre poly-typexpr et typexpr dans le manuel sans comprendre que les champs de structure pouvaient être typés différemment. Merci encore.

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

Discussions similaires

  1. [Ocaml][debutant] Une fonction qui fait Ci,j
    Par cladsam dans le forum Caml
    Réponses: 2
    Dernier message: 18/03/2007, 19h23
  2. [OCaml] Appel de fonction
    Par raph85 dans le forum Caml
    Réponses: 2
    Dernier message: 23/01/2007, 22h49
  3. Réponses: 6
    Dernier message: 12/03/2006, 15h41
  4. Fonction "polymorphe" ??
    Par rvzip64 dans le forum Langage
    Réponses: 7
    Dernier message: 03/03/2006, 15h36
  5. Fonction polymorphe et conteneur stl.
    Par Captain Fizzou dans le forum SL & STL
    Réponses: 2
    Dernier message: 29/11/2004, 19h13

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