Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 5 sur 5
  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    janvier 2010
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : janvier 2010
    Messages : 46
    Points : 48
    Points
    48

    Par défaut Petite question sur le typage des fonctions

    Bonjour,

    J'aimerai savoir pourquoi F# type la fonction (+) de la manière suivante:
    Code :
    val (+) : int -> int -> int
    et non pas quelque chose comme cela:
    Code :
    val (+) : 'a -> 'a -> 'a when 'a : INumerics
    Ce qui est d'autant plus étrange qu'elle accepte parfaitement l'expression suivante:
    et qu'un langage comme haskell dont le comportement de la fonction (+) est similaire, la type de la manière suivante :
    Code :
    (+) :: (Num a) => a -> a -> a

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : décembre 2005
    Messages : 10 162
    Points : 18 669
    Points
    18 669

    Par défaut

    surcharge des opérateurs en F#, ça explique tout
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  3. #3
    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 160
    Points
    1 160

    Par défaut

    Le type de l'opérateur + est celui-là :
    Code :
    1
    2
    3
    val inline (+) :
       ^a ->  ^b ->  ^c
        when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)
    Il faut qu'il existe une méthode statique + de type ^a * ^b -> ^c. Le caractère ^ indique que le type (peu importe lequel, mais un seul) doit être connu à la compilation. C'est donc différent de 'a où le type exact n'est pas forcément connu par le compilateur.

    Cela explique donc que 1+2, 3.2+1.4 et "hello "+"world" sont acceptés. Dans ton cas, tu n'as pas donné de contexte suffisant au compilateur pour savoir le type des arguments. Comme il ne pouvait pas deviner et qu'il avait besoin d'un type concret, il a utilisé le type par défaut. Ici, c'est int.

    Si tu définis une classe, tu as simplement besoin de définir la méthode (+) pour utiliser l'opérateur dessus. Il n'y a pas besoin de toutes les choses de INumerics.

  4. #4
    Membre du Club
    Homme Profil pro
    Inscrit en
    janvier 2010
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : janvier 2010
    Messages : 46
    Points : 48
    Points
    48

    Par défaut

    Citation Envoyé par LLB Voir le message
    Le type de l'opérateur + est celui-là :
    Code :
    1
    2
    3
    val inline (+) :
       ^a ->  ^b ->  ^c
        when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)
    Il faut qu'il existe une méthode statique + de type ^a * ^b -> ^c. Le caractère ^ indique que le type (peu importe lequel, mais un seul) doit être connu à la compilation. C'est donc différent de 'a où le type exact n'est pas forcément connu par le compilateur.

    Cela explique donc que 1+2, 3.2+1.4 et "hello "+"world" sont acceptés. Dans ton cas, tu n'as pas donné de contexte suffisant au compilateur pour savoir le type des arguments. Comme il ne pouvait pas deviner et qu'il avait besoin d'un type concret, il a utilisé le type par défaut. Ici, c'est int.

    Si tu définis une classe, tu as simplement besoin de définir la méthode (+) pour utiliser l'opérateur dessus. Il n'y a pas besoin de toutes les choses de INumerics.
    Je te remercie pour ta réponse

    Et dans le cas où je voudrais créer une fonction qui accepterait n'importe quel type numérique et sur lequel je voudrais faire des opérations arithmétique (addition, soustraction, etc), je dois m'y prendre comment ?

  5. #5
    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 160
    Points
    1 160

    Par défaut

    Une solution est de marquer la fonction en inline. Ce ne sera pas compilée comme une vraie fonction, elle sera spécialisée à chaque appel. Par exemple :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    > let inline dist x y = x * x + y * y |> float |> sqrt;;
    
    val inline dist :
       ^a ->  ^d -> float
        when  ^a : (static member ( * ) :  ^a *  ^a ->  ^b) and
             ( ^b or  ^c) : (static member ( + ) :  ^b *  ^c ->  ^e) and
              ^d : (static member ( * ) :  ^d *  ^d ->  ^c) and
              ^e : (static member op_Explicit :  ^e -> float)
    
    > dist 5 2;;
    val it : float = 5.385164807
    
    > dist 5.f 2.3f;;
    val it : float = 5.503635142
    Les types ont tendance à devenir rapidement énormes. Il ne faut pas en abuser, mais c'est très utile dans certains cas (Seq.sum utilise ça par exemple).

    Tu peux aussi passer par l'interface INumerics comme tu demandes. Tu as une explication et un exemple ici : http://cs.hubfs.net/forums/permalink...read.aspx#3824 (note que la fonction GetNumericAssociation est maintenant dans le PowerPack)

+ 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
  •