Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 4 sur 4
  1. #1
    Invité de passage
    Homme Profil pro Gérard Gauthier
    Développeur informatique
    Inscrit en
    septembre 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Nom : Homme Gérard Gauthier
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : septembre 2012
    Messages : 6
    Points : 4
    Points
    4

    Par défaut Problème de signature

    Je débute. Et je bute sur un problème régulièrement. Impossible d'écrire une signature de fonction acceptée par GHCi.
    Par exemple, la dernière fonction que j'ai écrite pour simplement résoudre une équation quadratique :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    quadratic a b c
     | delta < 0  = []
     | delta == 0 = [sol]
     | sol1<sol2  = [sol1, sol2]
     | otherwise  = [sol2, sol1] 
       where delta = b ^ 2 - 4.0 * a * c
             sol = (-b) / (2.0*a)
             sol1 = ((-b)+(sqrt delta))/(2.0*a)
             sol2 = ((-b)-(sqrt delta))/(2.0*a)
    Ca fonctionne. Alors j'essaie de la faire précéder de sa signature. Celle qui me parraît logique serait :
    Code :
     quadratic :: (Num a) => a -> a -> a -> [a]
    Mais non, GHCi se perd dans les inférences de type.
    Pas mieux avec :
    Code :
     quadratic :: (Floating a) => a -> a -> a -> [a]
    Ni même :
    Code :
     quadratic :: a -> a -> a -> [a]
    Alors je vais interroger GHCi en tapant :t quadratic et je vois que la signature est:
    Code :
    quadratic :: (Ord a, Floating a) => a -> a -> a -> [a]
    Soit mais alors qu'on dit qu'Haskell est concis, quelque chose m'échappe grandement. Je pensais que par la hiérarchie des types, il n'y avait pas à 'fouiller' dans les expressions ce qui relève de Ord, Floating, etc.

    Alors pourquoi fondamentalement je galère autant avec cet aspect basique qui est très décourageant avec tout ce que ce langage promet d'inférence. Je ne comprends toujours pas pourquoi il a fallu préciser le type le plus général de 'a' (Ord) et son plus restreint (Floating).

    Merci de vos lumières.

  2. #2
    Nouveau Membre du Club
    Inscrit en
    janvier 2007
    Messages
    64
    Détails du profil
    Informations personnelles :
    Âge : 35

    Informations forums :
    Inscription : janvier 2007
    Messages : 64
    Points : 39
    Points
    39

    Par défaut

    Salut gg373,
    Ord et Floating ne sont pas en connection hiérarchique, voit le diagramme sur:
    http://blogs.msdn.com/b/saeed/archiv...y-diagram.aspx

    Tu utilises le signe (<) dont la signature est:
    Code :
    (<) :: Ord a => a -> a -> Bool
    et la fonction sqrt:
    Code :
    sqrt :: Floating a => a -> a
    Donc forcément ta fonction doit spécifier elle aussi ces deux contraintes, sinon un utilisateur de ta fonction pourrait passer un paramètre inadéquat, comme une String.

    Mais tu peux spécifier des contraintes plus restrictives: par example RealFloat "descend" à la fois de Ord et Floating:
    Code :
    quadratic :: (RealFloat a) => a -> a -> a -> [a]
    fonctionne. Mais c'est généralement une meilleur idée de laisser le type le plus générique.

  3. #3
    Membre actif Avatar de Ptival
    Homme Profil pro Valentin Robert
    Étudiant
    Inscrit en
    juin 2004
    Messages
    70
    Détails du profil
    Informations personnelles :
    Nom : Homme Valentin Robert
    Âge : 25
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2004
    Messages : 70
    Points : 153
    Points
    153

    Par défaut

    Bonjour,

    La signature inférée par GHC est :

    Code :
    quadratic :: (Ord a, Floating a) => a -> a -> a -> [a]
    C'est le cas parce que :
    - tu utilises un opérateur de comparaison sur une valeur du type a ;
    - tu utilises l'opérateur de division sur une valeur de type a.

    Le problème, c'est que lorsque tu écris :

    Code :
    quadratic :: (Num a) => a -> a -> a -> [a]
    ou

    Code :
    quadratic :: (Floating a) => a -> a -> a -> [a]
    Aucune de ces deux signatures ne garantit qu'il existe un ordre sur a.

    ---

    Par la suite, je ne comprends pas vraiment ce qui t'importune.
    Le fait qu'il n'y ait pas un nom pour "un type qui est à la fois Floating et Ord" ?
    Cela me semble plutôt raisonnable, puisque donner un nom à chaque combinaison serait exponentiel (et les noms deviendraient définitivement ridicules).

    Le fait qu'il soit dur d'écrire une signature de type par soi-même ? C'est justement pour ça que l'inférence de type est appréciable, tu demandes simplement à GHC d'inférer pour toi le type le plus général. Comme tu l'as fait. La plupart des éditeurs te permettent même d'écrire cette signature inférée pour toi au bon endroit.

    Mais sinon, oui c'est assez ennuyant de deviner soi-même un type général pour un terme.

  4. #4
    Invité de passage
    Homme Profil pro Gérard Gauthier
    Développeur informatique
    Inscrit en
    septembre 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Nom : Homme Gérard Gauthier
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : septembre 2012
    Messages : 6
    Points : 4
    Points
    4

    Par défaut

    Bonjour !

    Merci de vos réponses lumineuses. Je débute avec l'excellent ouvrage de Miran Lipovaca. Je me demande s'il y a mieux dans ce cas...

    @Ptival : oui mon message est un peu confus car c'est en le rédigeant que j'ai réalisé que je pouvais demander la signature à GHCi. Et finalement, c'est une excellente pratique. Et puis aussi j'avais tout simplement mal assimilé la hiérarchie des types et classes. J'ai honte.

    @kaukau : okey, j'avais jeté une oeil (trop) rapide à cette hiérarchie et il me semblait si intuitif que Num dérive (c'est le mot correct dans le monde Haskell ?) de Ord. Ce n'est pas le cas. Est-ce pour permettre l'implémentation de nombres non ordonnables comme les nombres complexes que l'on n'a pas cet héritage ?

    Cordialement.

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
  •