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 :

Qu'est-ce qui est strict et qu'est-ce qui ne l'est pas ?


Sujet :

Haskell

  1. #1
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut Qu'est-ce qui est strict et qu'est-ce qui ne l'est pas ?
    J'ai 3 questions, en fait :

    Q.1) A propos des monades, j'aimerais savoir, est-ce que c'est seulement la monade IO qui est stricte ou bien est-ce que toutes les monades le sont ?


    Q.2) Et surtout, est-ce que les monades assurent que dans l'expression suivante :
    'f x' va être évalué AVANT g qui sera évalué AVANT h ? Je pense que oui, vu que je ne vois pas comment on peut obtenir le résultat de h sans avoir obtenu au préalable celui de g.
    Exemple avec Parsec (chap. 16 de Real World Haskell, ou on définit un parser HTTP) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    p_pair = liftM2 (,) (many1 p_char) (optionMaybe $ char '=' >> many p_char)
    Pour que le parsage marche comme on l'entend, il est nécessaire que le code en vert soit évalué avant ce qui est en rouge (et on est toujours dans du code pur).


    Q.3) Toujours concernant cet exemple de RWH, ils définissent dans le même chapitre GenParser comme un Applicative:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    instance Applicative (GenParser s a) where
       pure = return
       (<*>) = ap
    ce qui fait que le code précédent peut s'écrire de la sorte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    a_pair = liftA2 (,) (many1 a_char) (optionMaybe $ char '=' *> many a_char)
    Encore une fois, le fait que le premier arguement de 'liftA2 (,)' soit évalué AVANT le deuxième est-il assuré par les Applicatives ?
    Car cette fois-ci, par contre, dans l'expression :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    a = pure f <*> b <*> c <*> d
    b, c et d sont en théorie indépendants (c'est là la différence entre <*> et >>=) donc en théorie rien n'oblige Haskell à évaluer b avant c et c avant d.
    Du coup, je me demande, est-ce que le parser ne se comporte-t-il correctement que parce que son instance d'Applicative est construite avec des opérations de Monad ?
    Si c'est le cas, alors les Applicatives ne conviennent pas au parsage, et du coup c'est assez idiot de la part des auteurs de RWH de nous avoir sorti cet exemple.

  2. #2
    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
    1) Qu'est-ce que tu appelles une "monade stricte" ? Certaines opérations de la monade peuvent être strictes sans que toutes le soit. Je ne pense pas que le concept ait du sens (à moins de dire qu'une monade est stricte quand le >>= l'est, mais quand on parle de "monade IO" on prend aussi en compte toutes les opérations codées à l'intérieur de la couche IO).

    La grande majorité des opérations en Haskell n'est pas stricte, et la plupart des monades font tout paresseusement.

    2) Non, pas du tout. C'est paresseux. Il n'y a pas d'ordre temporel, par contre il y a un ordre logique : "x" sera donné à f, dont le résultat sera (modulo bind) donné à g, dont le résultat sera (modulo bind) donné à h. On pourrait imaginer une monade où bind (c'est à dire >>=) ignore son premier paramètre et ne renvoie rien, dans ce cas "f x" ne serait même pas évalué.

    Pour que le parsage marche comme on l'entend, il est nécessaire que le code en vert soit évalué avant ce qui est en rouge (et on est toujours dans du code pur).
    Non, le code que tu mets en valeur renvoie des parseurs. Tu peux évaluer les parseurs dans l'ordre que tu veux, du moment que tu appliques l'entrée au premier avant de donner le résultat au deuxième, et pas l'inverse.

    Tu confonds visiblement l'ordre d'évaluation et l'ordre d'application des fonctions.

    Pour la Q3, je ne connais pas les Applicative, donc je vais réserver mon avis pour l'instant, mais à ta place j'éliminerais l'hypothèse "les auteurs de RWH sont idiots".


    Je trouve que tu attaches trop d'importance à l'ordre d'évaluation. Haskell est un langage paresseux donc il est quasiment impossible de savoir précisément quand seront évaluées les valeurs, et ce ne sont pas des connaissances qui passent à l'échelle sur de plus gros codes. On s'en fout, tant que ça donne toujours le même résultat et que ça ne pose pas de problème de performances (CPU ou mémoire).
    D'autant plus que dans les exemples que tu donnes, l'évaluation n'a rien à voir avec le problème.

    Bon je suis allé voir la définition des Applicative. C'est pas inintéressant, mais je ne vois pas le rapport avec la choucroute. Dans <*> aussi il y a un lien de dépendance puisque tu appliques la fonction de l'argument de gauche à l'élément de l'argument de droite (le tout dans ta structure applicative), mais ce n'est pas non plus un lien sur l'ordre d'évaluation.

    Je crois que tu as du mal à conceptualiser ce que font les parseurs : tous ces symboles barbares qu'on a là ne servent pas à chainer les uns à la suite des autres des filtres sur une entrée, mais à composer des fonctions de parsing entre elles selon la structure qui nous plait, pour former une super-fonction de parsing qu'on appliquera un jour, si ça nous amuse, à une entrée. L'ordre dans lequel ces petits parseurs sont évalués pour construire ton gros parseurs, (et même le fait de savoir s'ils sont évalués ou pas, à priori ils ne le sont pas avant qu'on donne l'entrée, ça ne servirait pas à grand chose avec la structure qu'on a), ce n'est pas notre problème.

    Par contre évidemment si tu utilises le combinateur qui "prend un parseur f et un parseur g, et produit le parseur qui, si on lui donne une entrée, applique f à l'entrée puis g au résultat de f", oui quand le résultat du combinateur sera utilisé, tu peux être sur que f sera bien appliqué à l'entrée et pas g, d'ailleurs ça ne typerait même pas forcément.

  3. #3
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut
    Citation Envoyé par bluestorm Voir le message
    Tu confonds visiblement l'ordre d'évaluation et l'ordre d'application des fonctions.
    Effectivement, je comprends ce que tu veux dire. Donc, ce qu'assure le bind, c'est juste que dans 'f >>= g >>= h', f sera APPLIQUEE avant g qui elle même sera appliquée avant h ?

    Pour la Q3, je ne connais pas les Applicative, donc je vais réserver mon avis pour l'instant, mais à ta place j'éliminerais l'hypothèse "les auteurs de RWH sont idiots".
    Ce n'est pas ce que j'ai dit (je tiens pas à passer pour présomptueux). Ce que je voulais dire c'est : "si ce que je pense des applicatives est juste, l'exemple pouvait paraître idiot"

    Je trouve que tu attaches trop d'importance à l'ordre d'évaluation.
    Le souci c'est que tous les tutos/papiers trouvables sur le net ont un peu tendance à mélanger ou du moins à ne pais être extrèmement clairs en ce qui concerne ordre d'évaluation/ordre d'application, ainsi, on est rapidement confus. Si l'ordre d'évaluation n'a pas d'importance, alors c'est bien de l'ordre d'application dont je voulais parler.

    Citation Envoyé par bluestorm Voir le message
    Bon je suis allé voir la définition des Applicative. C'est pas inintéressant, mais je ne vois pas le rapport avec la choucroute. Dans <*> aussi il y a un lien de dépendance puisque tu appliques la fonction de l'argument de gauche à l'élément de l'argument de droite (le tout dans ta structure applicative)
    Tu ne m'as pas compris. Dans le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    -- (1)
    pure f <*> a <*> b <*> c
    a, b et c sont indépendants. b peut être calculé sans avoir calculé a au préalable, idem pour c et b. Quelque soit ce que renvoie a, b et c renverront la même chose. Alors que dans les monades:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    -- (2)
    a >>= b >>= c >>= f
    c ne renverra pas la même chose selon ce qu'il va recevoir de b.
    En gros, le code (1) en version monadique serait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    -- (3)
    do a' <- a
       b' <- b
       c' <- c
       return (f a' b' c')
    Tu vois que a', b' et c' servent uniquement à être passés en arguments à f.

    Les monades permettent de chaîner, pas les Applicatives, et un parser est constitué d'une chaîne de sous-parseurs, c'est ça qui fait que je pense que l'exemple du parsing ne s'adapte pas aux Applicatives.
    Et si c'était le cas, alors pourquoi GenParser n'est-il pas défini en standard comme un Applicative ?

  4. #4
    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
    Non : les applicative permettent de chaîner tout autant. Ton idée là d'application indépendante, c'est la façon dont tu t'imagines la chose, mais ça ne correspond pas à la réalité de l'ensemble des foncteurs applicatifs.

    L'interface des Applicatif te dit comment tu peux manipuler les objets _dans la structure_, au sein du foncteur "f" (des objets de type "f a" quoi). Elle ne te dit _rien_ de la structure elle-même, la signification du foncteur f. Si f implémente un chaînage, ton instance applicative va chaîner.

    Qu'on se mette bien d'accord pour commencer : le foncteur qu'on considère ici est le foncteur de parsec, (GenParser tok st) : c'est un foncteur qui prend un type "a", et qui renvoie le type du parseur qui va manger du des flux d'élément de type "tok", en maintenant un état "st", pour renvoyer un résultat de type "a". En gros "les parseurs qui te donnent du 'a'".

    NB : pour voir ce dont tu parlais je suis allé consulter :
    - la documentation de Control.Applicative
    - le texte de RWH
    - la documentation de Parsec.
    La prochaine fois que tu as une question, essaie de donner les URLs directement (particulièrement utile pour RWH où tu peux ancrer précisément la section qui te concerne).


    Pourquoi ce foncteur est-il une monade et un applicative ? Pour une monade, l'opération "return" est claire : tu prends un élément et tu renvoies un parseur qui renvoie cet élément, c'est à dire qui ne lit rien et le retourne direct. Du coup le "pure" de Applicatif est pareil, sauf qu'on prend une fonction.

    La partie intéressante c'est le 'bind' de la monade : m a -> (a -> m b) -> m b. On prend un parseur qui renvoie du a, et on a une fonction qui prend du a et renvoie un parseur qui renvoie du b. Facile : pour faire ça, on commence par utiliser le premier parseur sur notre entrée, et on donne le résultat (de type a) à la fonction (a -> m b), qui nous donne un parseur, qu'on applique ensuite à la suite de notre entrée, et on renvoie ce qu'il nous donne. Rajoute la propagation des erreurs du premier parsage et tu as exactement 'bind'.

    Maintenant qu'est-ce que c'est que le <*> d'applicative ? f (a -> b) -> f a -> f b. On a un parseur qui produit une fonction (a -> b) : bizarre. Imagine que tu parses un langage de programmation et que tu viens de lire le code d'un identifiant de fonction, ça te renvoie une fonction. Maintenant on te donne aussi un parseur sur a. Comment utiliser ces deux trucs pour avoir un parseur sur b ? Facile : on commence par utiliser le premier parseur, qui te renvoie la fonction parsée, puis derrière on utilise le deuxième qui te donne son argument (on parse un langage simple où l'argument est écrit juste derrière la fonction) : tu n'as plus qu'à appliquer l'argument à la fonction, et tu as un résultat de type b. Au final tu as bien un parseur qui renvoie du b, donc un f b.

    Tu remarques que dans ma définition applicative, je n'ai pas fait référence une seule fois aux monades. Je n'ai sûrement pas dérivé la définition de <*> de celle de bind. Mais dans notre cas (le parseur), il y a un chaînage entre les arguments de <*>, forcément : parce que notre foncteur sous-jacent implémente un état, qui bouge, et tu fais les choses dans l'ordre. Évidemment si tu parses un langage de programmation avec notation postfixe (fonction après l'argument), tu vas changer ta définition applicative pour parser l'argument avant la fonction. Mais à chaque fois, du point de vue de l'utilisateur de l'instance, il ne se passe rien : on applique une fonction à un paramètre, dans un foncteur, c'est tout. Il n'a pas à se soucier de l'état interne du foncteur (qui chaîne des trucs), c'est l'implémentation interne de "f" et ça ne le regarde pas.


    Dans ton message tu n'as pas cité le seul exemple de RWH où l'utilisation d'applicative a un peu d'intérêt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    a_hex = hexify <$> (char '%' *> hexDigit) <*> hexDigit
        where hexify a b = toEnum . fst . head . readHex $ [a,b]
    Comment lire ce code ? Tu as deux niveaux de lecture : celui du gars qui connaît l'implémentation et la signification de "f", et qui se prend le chou avec des petits détails (ordre d'évaluation gnagnagna), et celui du type qui voit ce code sans savoir ce que les tordus de #haskell ont encore trouvé comme définition de <$>, mais qui connaît les règles de base des Applicative et leur signification _générale_.

    Première lecture :
    - on commence par faire "pure hexify" : on parse pour ne rien lire et renvoyer directement hexify, c'est un parseur qui renvoie (hex -> hex -> foo) (je connais pas les types exacts)
    - ensuite on applique cette fonction, dans le foncteur f, à l'argument "char ... hexDigit" : on a parsé la fonction hexify, maintenant on parse son parmètre et on applique (je suis la définition de <*> pour les parseurs) : on a donc globalement un parseur qui renvoie du (hex -> foo), en commencant par ne rien faire puis en parsant (char ..hexDigit)
    - ensuite on applique cette fonction, dans le foncteur, à l'argument "hexDigit" : donc on parse l'hexdigit et on l'applique au reste

    Deuxième lecture : "<$>" c'est l'application d'une fonction, et "<*>" c'est le séparateur entre les arguments : on applique la fonction pure hexify aux deux arguments (char *> HexDigit) et Hexdigit, tout en faisant la tritouille du foncteur en arrière plan. (char *> HexDigit) ça ignore la valeur char (modulo la tritouille), donc en gros on applique la fonction à deux HexDigit quoi.

    Pour comprendre du code utilisant Parsec avec des applicative, il faut un style intermédiaire : savoir voir (char *> HexDigit) et HexDigit comme des arguments indépendants donnés à une fonction hexify, mais aussi tenir compte du fait que dessous, on tripatouille l'entrée de l'utilisateur. Mais pas trop en tenir compte, et pas trop chercher à savoir comme ça marche, qui est évalué où et dans quel ordre, sinon tu perds la vision d'ensemble et tu comprends plus rien.


    Pourquoi Parsec n'a pas été codé avec des Applicative ? Parce que les monades sont strictement plus puissantes. Ce que te permets de faire bind (m a -> (a -> m b) -> m b) c'est de parser un truc, puis de choisir le parseur suivant en *fonction* du résultat. Selon la valeur parsée tu peux continuer selon des parseurs *différents*. Par exemple tu peux parser dynamiquement ta grammaire en ajoutant au fur et à mesure des syntaxes complètement différentes selon ce que tu lis (tiens c'est un "<?php" je vais lui coller un parseur de PHP aux fesses).

    Applicative ne permet pas ça : quand tu dis que les paramètres sont indépendants, c'est que quel que soit le résultat du parsing du début, la fin va être parsée de la même façon (pas en renvoyant le même résultat, mais selon les mêmes règles). En règle générale ça suffit, mais le type qui aura besoin de dynamise devra prendre une monde.

    Te lamente pas non plus, en fait les monades c'est nul aussi pour parser : quand tu t'intéresses vraiment à la question tu découvres un nouveau truc trop puissant qui fait que la *bonne* structure ce sont les Arrows. Enfin c'est que les chercheurs sur le sujet ont dit, j'ai pas vraiment regardé, et de toute façon ce sera vrai que jusqu'au moment où on voudra faire des trucs encore plus forts.


    Donc les Applicative, c'est adapté dans les cas où ta grammaire est statique. Indépendamment de ce genre de questions, je pense que si les auteurs de RWH en parlent pour ça, c'est pas en raison de ce genre de considérations, mais parce qu'ils ont envie de montrer aux gens comment on fait joujou avec les Applicative, ils ont pris le premier exemple concret qui leur tombait sous la main (sachant que tout le monde a honte de l'exemple avec Ziplist qui est laid et montre juste les déficits du système de typage ML, en plus des défauts des type classes avec les overlapping instances).

  5. #5
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut
    Merci d'avoir pris le temps d'écrire une aussi longue réponse. Effectivement, je comprends ce que tu veux dire.
    Pourquoi Parsec n'a pas été codé avec des Applicative ? Parce que les monades sont strictement plus puissantes. Ce que te permets de faire bind (m a -> (a -> m b) -> m b) c'est de parser un truc, puis de choisir le parseur suivant en *fonction* du résultat. Selon la valeur parsée tu peux continuer selon des parseurs *différents*. Par exemple tu peux parser dynamiquement ta grammaire en ajoutant au fur et à mesure des syntaxes complètement différentes selon ce que tu lis (tiens c'est un "<?php" je vais lui coller un parseur de PHP aux fesses).
    Ouaip, c'est justement ça que je disais, avec une monade tu peux adapter les traitements de ta chaine de fonctions en fonction de ce qu'elles reçoivent. Ce que je n'avais pas réalisé c'est que les Applicatives chaînent aussi.

    Te lamente pas non plus, en fait les monades c'est nul aussi pour parser : quand tu t'intéresses vraiment à la question tu découvres un nouveau truc trop puissant qui fait que la *bonne* structure ce sont les Arrows. Enfin c'est que les chercheurs sur le sujet ont dit, j'ai pas vraiment regardé, et de toute façon ce sera vrai que jusqu'au moment où on voudra faire des trucs encore plus forts.
    Ah ? Tiens, je trouvais les monades réellement bien adaptées à ce type d'application.
    Pour ce qui est des Arrows, je sais qu'elles ont tendance à être présentées un peu comme le Saint Graal de Haskell, mais sont-elles réellement utilisées actuellement par une majorité de développeurs, ou bien seulement par les "mighty warlords" du langage ?

  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
    Une "majorité de développeurs" ? On parle de Haskell je te rappelle, le langage pour l'évolution duquel le fait de ne pas avoir d'utilisateurs sérieux a été l'atout majeur.
    Les Arrows sont présentes dans certaines bibliothèques importantes, et tout le monde se la pète en plaçant un petit combinateur de temps en temps, mais quelle est la proportion des utilisateurs qui connaissent vraiment, je ne sais pas (quand on voit que certains racontent à tout le monde que Haskell c'est vraiment trop bien alors qu'ils ne comprennent pas les monades). Je me souviens avoir entendu dire par contre qu'une des vénérables libs Haskell pour manipuler du XML (HXML peut-être ou un truc comme ça) n'était utilisée par personne car son interface arrowesque était "trop compliquée pour le commun des mortels".


    Les arrows sont en fait complètement dans le sujet ici, parce qu'en deux mots elles réunissent Monad et Applicative en un seul concept. Le problème des Monad en effet c'est que tu peux choisir ton parseur dynamiquement, mais c'est pas juste un choix, tout passe par bind donc du coup _tout_ est dynamique; dans la vraie vie, on veut avoir aussi des informations statiques à disposition, pour pouvoir fait des choix plus éclairés avant de lancer le calcul. Le manque d'information donne lieu à des problèmes d'efficacité (pas d'information, pas d'optimisation), en particulier des memory leaks dus aux implémentations trop naïves du backtracking imposées par l'interface monadique.
    Les arrows mélangent informations statiques et dynamiques pour pouvoir avoir un truc flexible mais optimisé quand même. Mais du coup c'est nettement plus complexe : ça c'est peut-être tassé depuis mais il y a quelques années les chercheurs n'étaient pas d'accord entre eux sur l'interface à demander et surtout les _lois_ à imposer; il y a avait 21 lois ou un truc comme ça, bref du grand n'importe quoi.

    Tu trouveras une présentation des Arrows vachement accessible (et des Monades aussi d'ailleurs) dans le papier fondateur de Huges à ce sujet. Il doit y avoir d'autres liens pertinents sur le site Haskell mais sans doute aucun aussi adapté pour un débutant qui a le temps de comprendre les choses.

  7. #7
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut
    Citation Envoyé par bluestorm Voir le message
    Une "majorité de développeurs" ? On parle de Haskell je te rappelle, le langage pour l'évolution duquel le fait de ne pas avoir d'utilisateurs sérieux a été l'atout majeur.
    Oui, enfin Haskell commence à être pas mal utilisé par les professionnels, non ?

    Les Arrows sont présentes dans certaines bibliothèques importantes, et tout le monde se la pète en plaçant un petit combinateur de temps en temps, mais quelle est la proportion des utilisateurs qui connaissent vraiment, je ne sais pas (quand on voit que certains racontent à tout le monde que Haskell c'est vraiment trop bien alors qu'ils ne comprennent pas les monades). Je me souviens avoir entendu dire par contre qu'une des vénérables libs Haskell pour manipuler du XML (HXML peut-être ou un truc comme ça) n'était utilisée par personne car son interface arrowesque était "trop compliquée pour le commun des mortels".
    En gros, jusqu'à ce que les ténors d'Haskell simplifient leur utilisation, on peut s'en passer, c'est ça ?

    Tu trouveras une présentation des Arrows vachement accessible (et des Monades aussi d'ailleurs) dans le papier fondateur de Huges à ce sujet. Il doit y avoir d'autres liens pertinents sur le site Haskell mais sans doute aucun aussi adapté pour un débutant qui a le temps de comprendre les choses.
    Merci pour le lien

  8. #8
    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
    Oui, enfin Haskell commence à être pas mal utilisé par les professionnels, non ?
    Non. Il faut pas confondre buzz sur le net et utilisation professionnelle. T'as qu'à aller voir sur le forum "Best of des débats qui tournent en rond pour les vrais pros de l'info, on est pas des merdes ici" sur ce même site, personne connaît Haskell.
    Après bien sûr, quel que soit le langage de niche tu auras toujours deux ou trois start-up fondées par des PhD du MIT qui sont à fond dans le truc, gagnent du fric et organisent des conférences "notre langage ésotérique il déchire". J'ai même entendu quelqu'un dire une fois que le but quand on a très bon langage de programmation, c'est pas de convaincre les autres gens de l'utiliser (c'est trop chiant), mais de s'en servir pour faire un produit qui torche et damer le pion à la concurrence qui utilise des langages de moches.

    En gros, jusqu'à ce que les ténors d'Haskell simplifient leur utilisation, on peut s'en passer, c'est ça ?
    C'est pas ce que j'ai dit. La plupart des gens s'en passent faute de besoin et peut-être de connaissances, après c'est à toi de voir au cas par cas : si c'est le plus adapté à ton problème, utilise le, sinon non. Le truc c'est que plus c'est générique comme les monades ou arrows, plus c'est facile de se dire "tiens c'est une monade" "tiens c'est une arrow"; si tu veux pas ajouter de la complexité inutile à ton projet il faut savoir quand les avantages de l'abstraction dépassent son coût en complexité logicielle. Si tu en fais trop, toi tu seras à fond dans le trip et tu t'en rendras pas forcément compte, par contre quand tu vas passer ton code à un codeur innocent (même bon en Haskell) en espérant qu'il code avec toi, il va se prendre un mur.

    De toute façon, si tu cherchais dans un langage avec avant tout des fonctionnalités "simples d'utilisation", tu coderais pas en Haskell.


    Par ailleurs, ce genre de trucs tu te dis pas à l'avance "tiens je vais coder ça et hum je sens bien que ça aura une structure de monade", en tout cas pas sans avoir une grande expérience derrière toi. Ça vient plutôt après la bataille, tu regardes ton truc et tu te dis "Ah tiens en fait ma structure principale est une monade", là tu refactorises en utilisant les opérations quivontbien, t'es heureux parce que ton code a diminué en taille, et ça facilite les extensions futures. Jusqu'à l'extension qui te demande plus qu'une monade, et qui te fera reconsidérer le truc, refactoriser à nouveau, etc.

    Ces instances sont utiles quand elles établissent un lien entre des idées abstraites et la structure concrète du domaine sur lequel tu travailles : en général, avant de commencer à mettre les mains dans le cambouis tu n'as pas assez d'intuition sur la structure de ton problème, donc tu ne peux pas voir ces liens. Ça vient après, quand t'as sué, et que tu repères un pattern. Il y a sûrement des gens qui ont assez d'expérience pratique pour sauter l'étape bricolage de départ et passer directes à des représentations abstraites, mais ça tu le sauras quand ça t'arrivera.

  9. #9
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut
    Citation Envoyé par bluestorm Voir le message
    Non. Il faut pas confondre buzz sur le net et utilisation professionnelle. T'as qu'à aller voir sur le forum "Best of des débats qui tournent en rond pour les vrais pros de l'info, on est pas des merdes ici" sur ce même site, personne connaît Haskell.
    Que veux-tu, y'a des ignares partout

    Après bien sûr, quel que soit le langage de niche tu auras toujours deux ou trois start-up fondées par des PhD du MIT qui sont à fond dans le truc, gagnent du fric et organisent des conférences "notre langage ésotérique il déchire". J'ai même entendu quelqu'un dire une fois que le but quand on a très bon langage de programmation, c'est pas de convaincre les autres gens de l'utiliser (c'est trop chiant), mais de s'en servir pour faire un produit qui torche et damer le pion à la concurrence qui utilise des langages de moches.
    Pourquoi pas, après tout ils sont ainsi récompensés d'avoir eu l'intelligence d'utiliser un bon langage.

    Si tu en fais trop, toi tu seras à fond dans le trip et tu t'en rendras pas forcément compte, par contre quand tu vas passer ton code à un codeur innocent (même bon en Haskell) en espérant qu'il code avec toi, il va se prendre un mur.
    C'est l'impression que j'avais en démarrant le Haskell, j'avais peur que les Monades et tous leurs amis soient le gros truc qui épate la gallerie mais qui s'avère juste être au final de la poudre aux yeux. Au final non, je trouve ça classe mais utile et surtout bien pensé.

    De toute façon, si tu cherchais dans un langage avec avant tout des fonctionnalités "simples d'utilisation", tu coderais pas en Haskell.
    Bah, d'aucuns te diraient que ça dépend de ta culture. Comme tu l'as dit, après pas mal de pratique on commence à voir là où les outils Haskell vont bien, et à tirer parti de leur simplicité.

    Ces instances sont utiles quand elles établissent un lien entre des idées abstraites et la structure concrète du domaine sur lequel tu travailles : en général, avant de commencer à mettre les mains dans le cambouis tu n'as pas assez d'intuition sur la structure de ton problème, donc tu ne peux pas voir ces liens. Ça vient après, quand t'as sué, et que tu repères un pattern. Il y a sûrement des gens qui ont assez d'expérience pratique pour sauter l'étape bricolage de départ et passer directes à des représentations abstraites, mais ça tu le sauras quand ça t'arrivera.
    Oui, enfin c'est un peu la même dans tous les langages. Ce n'est qu'après avoir codé 18 classes en objet que tu te rends compte qu'il y en a une petite dizaine qui ont un comportement commun, et que tu te lances à faire des classes de base et de l'héritage qui va bien.

Discussions similaires

  1. Réponses: 1
    Dernier message: 28/07/2010, 09h06
  2. Réponses: 2
    Dernier message: 03/05/2010, 16h11
  3. Réponses: 21
    Dernier message: 05/04/2008, 20h30

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