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

Haskell Discussion :

[Débutant] Léger soucis avec les Types


Sujet :

Haskell

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 30
    Points : 24
    Points
    24
    Par défaut [Débutant] Léger soucis avec les Types
    Bonjour,

    Je débute un peu en Haskell et je voudrais faire une petite "calculatrice". J'ai déjà un petit soucis avec un code et je voudrais votre aide, il est surement possible de le faire autrement mais je voudrais quand même le faire comme je l'ai fait, juste pour tester et apprendre de mes erreurs.

    Voilà le terrible code, ne vous moquez pas, ce n'est que le début hein . Le code est inspirer de l'exemple de DA-OCAML. Je veux donc un type "touche" qui représente les touches +, -, *, /, =, 1, 2 ...9. Puis je veux tester si un nombre "x" est compris entre 0 et 9.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
    data touche = Plus | Moins | Fois | Par | Egal | Chiffre of Int
     
     
    estChiffre x
        | x (<= 9 && >= 0) = True
    	| otherwise = False
    Il aime pas la déclaration de "touche" .

    Merci de votre aide,


    Zooix

  2. #2
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Il y a quelques contraintes sur les noms en Haskell, entre autres les noms de type et les constructeurs de données doivent commencer par une majuscule (et il n'y a pas de "of" dans les déclarations des constructeurs) alors que les noms de variables (fonctions, valeurs ou types) doivent commencer par une minuscule :
    Code Haskell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    data Touche = Plus | Moins | Fois | Par | Egal | Chiffre Int
     
    estChiffre x = 0 <= x && x <= 9
    Par ailleurs "x (<= 9 && >= 0)" n'est pas correct : ce serait l'application de x à l'expression (<= 9 && >= 0) qui est elle-même syntaxiquement incorrecte.

    Je remarque également un anti-pattern :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    predicat x
      | "expression sur x" = True
      | otherwise = False
    "expression sur x" doit renvoyer un booléen (Bool) pour pouvoir être utilisé dans une garde comme ici, tu peux donc utiliser directement cette expression plutôt que de faire un "if e then True else False" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    predicat x = "expression sur x"
    C'est une "erreur" courante parmi les débutants en programmation.

    N'hésite pas à poser toutes tes questions sur ce forum : c'est pas comme si on était submergé, la communauté française Haskell est malheureusement plus restreinte que la communauté mondiale (prédominance d'OCaml dans l'enseignement, par solidarité nationale probablement). Tu peux également jeter un coup d'oeil à #haskell.fr sur irc.freenode.net si tu connais IRC (#haskell est très animé et amical mais malheureusement en anglais).

    J'ai récemment croisé des notes de cours en français sur le même sujet (calculatrice) à cette adresse (il y a plusieurs messages sur le sujet, dont une correction).
    --
    Jedaï

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 30
    Points : 24
    Points
    24
    Par défaut
    Merci bien Jedai.

    J'ai donc corriger mon code, tout marche (enfin pour ce qu'il y a ). Je re-poste ici si je bloque où je passe sur IRC si j'ai le temps.

    Au début je voulais juste bidouiller un peu, j'avais donc modifié un bout de code qui parsait et évaluait une notation polonaise inversée. Je l'ai perdu il y a plusieurs mois et maintenant je veux faire un parseur et "évaluateur" de maths "normales", genre (5*4)+12 . Je ne sais pas tellement par où commencer, je peux pour le moment parser la chaine, après faut que je réfléchisse un pue plus à la méthode à employer.

    Merci en tout cas.

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 30
    Points : 24
    Points
    24
    Par défaut
    J'ai une question: Que fait foldl exactement ?
    J'ai regardé ici: http://haskell.org/ghc/docs/latest/h...e.html#v:foldl, mais je ne comprends pas trop, ça réduit des listes ? Idem pour le '.', je ne vois pas trop à quoi cela correspond.

    Si quelqu'un pouvait me donner des détails sur foldl et '.', ainsi que ce que sur l'apostrophe inversée "`", cela serait sympa.

    Merci d'avance.

  5. #5
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    foldl est un fold, tu le trouveras sous le nom de fold_left, reduce, inject... selon les langages, sa définition sur les listes est simple :
    Code Haskell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    foldl f y [] = y
    foldl f y (x:xs) = foldl f (f y x) xs

    Prenons un exemple simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    foldl (+) 0 [1,2,3] 
    == foldl (+) (0 + 1) [2,3]
    == foldl (+) ((0+1) + 2) [3]
    == foldl (+) (((0+1) + 2) + 3) []
    == ((0+1) + 2) + 3
    Avec une fonction quelconque :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foldl f 0 [1,2,3] == f (f (f 0 1) 2) 3
    Dans les langages stricts, foldl est souvent apprécié parce qu'il est terminalement récursif, autrement dit il est possible d'optimiser le code généré pour que foldl n'accumule pas ses appels récursifs dans la pile. En Haskell la situation est plus ambigüe parce que bien que foldl en lui-même ne puisse pas provoquer de dépassement de pile, il peut créer des thunks (des bouts de code en attente d'évaluation) qui eux provoque un tel débordement. "foldl (+) 0" est lui-même sujet à ce problème. C'est pourquoi il est extrêmement rare de voir foldl dans un programme réel en Haskell, tu trouveras plutôt foldr ou foldl' à la place. Je te renvoie à cette page du wiki pour une explication plus en profondeur.


    Les backquotes ` sont utilisés pour transformer une fonction normale en opérateur infixe, tout comme les parenthèses () sont utilisés pour transformer un opérateur infixe en fonction normale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    préfixe : (+), f
    infixe : +, `f`
    Il y a un certain nombre de fonctions en Haskell qui sont plutôt prévues pour être utilisées en infixe : elem ou mplus par exemple.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    5 `elem` [1..10], (5 `elem`), (`elem` "+*-/")
    Nothing `mplus` Just 5
    Enfin (.) : c'est un opérateur infixe, au même titre que (+) ou (*), il s'agit de la composition de fonctions. En Mathématiques tu as sûrement vu que si tu avais deux fonctions f et g, tu pouvais les combiner f•g (souvent lu "f rond g" ou "f après g") de sorte que (f•g)(x) soit équivalent à f(g(x)). (.) est l'opérateur Haskell qui fait ça, sa définition est simplement :
    Haskell est très bien adapté au style dit "pointfree" ("libre du point" "sans points", le "point" ici désignant les arguments explicite, comme x dans la définition "f x = x + 5") et l'opérateur (.) est un élément essentiel pour ce style combiné avec les fonctions d'ordre supérieur.

    Par exemple cette fonction vérifie que tous les mots d'une chaîne de caractère sont capitalisés (leur première lettre est majuscule) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    capitalisedSentence = all (isUpper . head) . words
    Ca se lit de droite à gauche : on découpe en mots (words), puis on vérifie que pour tous les mots (all) leur première lettre (head) est une majuscule (isUpper)

    Ce style est considéré élégant et permet souvent d'exprimer avec concision et clarté des idées fort complexe. Il est néanmoins possible d'aller trop loin, d'où la blague qui consiste à appeler ce style "pointless" (qui pourrait se traduit par "sans point" mais signifie "inutile" en anglais), c'est une question d'équilibre.

    --
    Jedaï

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 30
    Points : 24
    Points
    24
    Par défaut
    Merci à toi,

    Je cherche depuis quelques temps et j'arrive pas à me faire un parseur + évaluateur de syntaxe qui prendrait par exemple "2+3" en entrée et qui renverrait 5.

    Tu as pas une idée ? Car je patauge un peu là .

    Merci en tout cas pour tes explications sur foldl, '.' et `elem` .

  7. #7
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Je te recommanderais de faire un tour vers Parsec, c'est une librairie pour écrire des parseurs monadiques en Haskell, elle est tout à fait capable de faire ce que tu demandes.
    Si le but est pratique et non pédagogique, Parsec.Expr et Parsec.Language résolve le problème sans avoir à trop y réfléchir.

    --
    Jedaï

Discussions similaires

  1. Réponses: 2
    Dernier message: 20/03/2011, 19h37
  2. [Débutant] problème avec les types de variables
    Par mitmit dans le forum Débuter
    Réponses: 10
    Dernier message: 14/02/2008, 11h40
  3. [MySQL] Type text et souci avec les varchar
    Par Atharendil dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 17/09/2006, 22h51
  4. Réponses: 7
    Dernier message: 05/10/2004, 13h44
  5. [Débutant][Phppgadmin] problème avec les types
    Par PoY dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 19/08/2004, 17h06

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