Y a-t-il des inconvénients ou des problèmes avec Haskell?

47

Je cherche à plonger dans Haskell pour mon prochain projet personnel (relativement trivial). Les raisons pour lesquelles je m'attaque à Haskell sont les suivantes:

  1. Me lancer dans un langage purement fonctionnel
  2. La vitesse. Bien que je sois sûr que cela puisse être discuté, le profil que j’ai vu des clous Haskell proches du C ++ (et qui semble être un peu plus rapide que Erlang).
  3. La vitesse. Le serveur Web de Warp semble être fou rapide par rapport à pratiquement tout le reste .

Donc, étant donné cela, ce que je recherche, ce sont les inconvénients ou les problèmes qui accompagnent Haskell. Le Web contient énormément d’informations sur les raisons pour lesquelles Haskell est une bonne chose, mais je n’ai pas trouvé beaucoup de sujets sur son côté laid (à part des reproches sur sa syntaxe qui ne me dérangent pas du tout).

Un exemple de ce que je recherche pourrait être le GIL de Python. Quelque chose qui n'a pas fait son chemin jusqu'à ce que je commence vraiment à envisager l'utilisation de la simultanéité dans un environnement CPython.

Demian Brecht
la source
4
Trouvé ceci sur stackoverflow: stackoverflow.com/questions/1695076/pros-and-cons-of-haskell
FrustratedWithFormsDesigner
26
J'ai entendu dire que des programmeurs moins expérimentés avaient traité des problèmes de fonte des cerveaux. C'est une condition très chère à traiter.
ChaosPandion
1
@FrustratedWithFormsDesigner: Merci pour le lien. Cependant, il n'y a toujours aucune référence à aucun inconvénient technique par rapport à Haskell. Serait-ce qu'il n'y en ait pas ? ;)
Demian Brecht
6
@ChaosPandion: J'ai entendu le même .. Mais si vous ne faire fondre votre cerveau, êtes - vous réellement essaie ? ;) De plus, je ne me considérerais pas vraiment comme un programmeur de moindre importance, je ne m'inquiète donc pas trop pour cela;)
Demian Brecht
3
@ ChaosPandion: Et la plupart des régimes de santé ne le couvrent pas. :(
FrustratedWithFormsDesigner

Réponses:

48

Quelques inconvénients auxquels je peux penser:

  • En raison de la nature de la langue et de ses racines solides dans le monde universitaire, la communauté est très soucieuse des mathématiques; Si vous êtes une personne pragmatique, cela peut parfois être accablant, et si vous ne parlez pas le jargon, vous aurez plus de difficulté que dans beaucoup d'autres langues.
  • Bien qu'il existe une richesse incroyable de bibliothèques, la documentation est souvent laconique.
  • Les tutoriels d'entrée de gamme sont rares et difficiles à trouver. La courbe d'apprentissage initiale est donc assez raide.
  • Quelques fonctionnalités linguistiques sont inutilement maladroites; Un exemple frappant est la façon dont la syntaxe d'enregistrement n'introduit pas d'étendue de dénomination. Il est donc impossible de définir le même nom de champ d'enregistrement dans deux types différents dans le même espace de nom de module.
  • Haskell adopte par défaut une évaluation paresseuse. Bien que ce soit souvent une bonne chose, cela peut parfois vous faire mal. Utiliser naïvement une évaluation paresseuse dans des situations non triviales peut entraîner des goulots d'étranglement inutiles en termes de performances. Comprendre ce qui se passe sous le capot n'est pas tout à fait simple.
  • Une évaluation paresseuse (associée en particulier à la pureté et à un compilateur optimisant de manière agressive) signifie également que vous ne pouvez pas facilement raisonner à propos de l'ordre d'exécution; en fait, vous ne savez même pas si un certain morceau de code est réellement évalué dans une situation donnée. Par conséquent, le débogage du code Haskell nécessite un état d'esprit différent, ne serait-ce que parce que parcourir votre code est moins utile et moins significatif.
  • En raison de la pureté de Haskell, vous ne pouvez pas utiliser les effets secondaires pour faire des choses comme I / O; vous devez utiliser une monade et une évaluation «abusive» paresseuse pour obtenir une interactivité, et vous devez faire glisser le contexte monadique partout où vous voudrez peut-être effectuer des E / S. (Ceci est en fait une bonne fonctionnalité à bien des égards, mais cela rend parfois impossible le codage pragmatique.)
tdammers
la source
16
Il existe actuellement de très bons livres d’introduction disponibles gratuitement en ligne. Learn You a Haskell for Great Good est l'un des meilleurs livres de programmation pour débutants que j'ai jamais lus et Real World Haskell est une excellente ressource intermédiaire.
Tikhon Jelvis
1
@TikhonJelvis: Ce sont en effet les deux seuls candidats que je trouve utile d'utiliser; "Learn You A Haskell" m'a confondu plus que tout, "Real World Haskell" a fonctionné pour moi, mais suppose un peu d'expérience en programmation. Il y a aussi "Gentle Introduction to Haskell", mais c'est tout sauf doux, surtout si vous n'avez pas de formation en mathématiques.
tdammers
J'utilise "Gentle Introduction to Haskell" et "Real World Haskell". La combinaison des deux m'a fourni beaucoup d'informations utiles. Je suis à un niveau où je suis prêt pour un projet non trivial mais malheureusement, je n'ai pas beaucoup de temps pour le faire.
Giorgio
9
"si vous êtes une personne pragmatique ...": l'utilisation d'un langage orienté vers les mathématiques peut parfois s'avérer très pragmatique si elle vous évite beaucoup de corrections de bugs par la suite. Bien sûr, vous devez toujours trouver un équilibre entre le temps que vous gagnez en utilisant un outil et le temps supplémentaire dont vous avez besoin pour apprendre à vous en servir.
Giorgio
Les monades fonctionneraient (et fonctionnent dans d'autres langues) exactement de la même manière dans une langue stricte. Vous ne devez absolument pas "abuser" d'une évaluation paresseuse pour obtenir une interactivité, il est donc trivial d'écrire un programme interactif strict en Haskell.
Point
19

La plupart des inconvénients de Haskell (ainsi que l'essentiel de ses avantages) proviennent de ses deux caractéristiques déterminantes: il est paresseux et purement fonctionnel.

Être paresseux rend plus difficile la raisonnement sur la performance. Surtout pour les personnes qui ne sont pas habituées à la paresse, mais même pour les Haskellers expérimentés, il peut être difficile de voir comment la paresse affectera les performances dans certains cas.

La paresse signifie également qu'il est plus difficile de créer des repères précis sans utiliser des bibliothèques telles que Criterion.

Être purement fonctionnel signifie que chaque fois que vous aurez besoin d'utiliser des structures de données modifiables (dans les cas où il n'est pas possible d'obtenir la performance souhaitée sans elles - bien que, grâce à l'optimiseur de GHC, cela ne se produise pas aussi souvent que vous ne le pensez), coincé dans la monade IO (ou ST), ce qui rend le code plus lourd.

Puisque vous avez mentionné la vitesse parmi vos objectifs, je tiens à souligner qu’il existe souvent d’énormes différences de performances entre le code Haskell optimisé à la main et le code Haskell qui a été écrit sans trop réfléchir aux performances (plus que dans d’autres langues). Et le code Haskell optimisé à la main est souvent très laid (bien que je suppose que cela est également vrai dans la plupart des autres langues).

sepp2k
la source
1
Purement fonctionnel est en fait une caractéristique de vente, pas un inconvénient. Une langue "paresseuse" n'a pas de sens, paresseux vs strict est une question de types, et les types paresseux et strict ont leurs utilisations. (Donc , Haskell est tout aussi estropié de ne pas avoir des types strictes que la plupart des langues sont paralysés par ne pas avoir les types paresseux.) Principaux inconvénients de Haskell sont son système de module merdique (modules ne sont pas de première classe) et les classes de type fait réellement briser la modularité (la La règle "une instance par type" oblige le compilateur à conserver une liste globale d'instances de classes de types).
Pyon
21
"Et le code Haskell optimisé à la main est souvent très laid (bien que je suppose que cela soit également vrai dans la plupart des autres langues)." Cette. Lorsque les utilisateurs veulent montrer l’élégance de Haskell, ils publient un code court et attrayant, ce qui vous donnerait malheureusement de très mauvaises performances s’il était exécuté sur une quantité de données comparable à celle de la production. Quand les gens veulent montrer que "Haskell est aussi rapide que C ++", ils publient du code compliqué et difficile à lire, qui est toujours plus lent qu'une version beaucoup plus lisible en C.
quant_dev
12

Je ne suis pas un expert de Haskell: j'ai appris les bases mais, malheureusement, je n'ai pas eu la chance de faire un projet sérieux à Haskell (j'aimerais bien, car j'aime beaucoup cette langue).

Cependant, d'après ce que je sais et d'après une discussion avec quelqu'un qui travaille dans un domaine proche de la programmation fonctionnelle, Haskell n'est peut-être pas la meilleure solution lorsque vous souhaitez implémenter des algorithmes de graphes, où vous devez par exemple parcourir le graphique et effectuer des analyses. beaucoup de changements locaux sur la structure du graphe.

Comme un graphe n’a généralement pas de structure récursive, j’estime que la meilleure approche consiste à construire une copie du graphe en utilisant des structures et des pointeurs entre eux (comme vous pouvez le faire par exemple en C ++) et à manipuler cette copie en modifiant les pointeurs. créer ou détruire des nœuds, etc.

Je me demande comment de telles structures et opérations de données peuvent être traitées correctement dans Haskell, car à ma connaissance, il n'est pas possible d'utiliser la représentation / approche ci-dessus. Certains problèmes liés aux algorithmes de graphes dans Haskell sont brièvement décrits dans cet article.

MODIFIER

J'ai récemment parlé à un expert en programmation fonctionnelle et il a confirmé que la mise en œuvre efficace de certains algorithmes de graphes peut être assez délicate en Haskell: déplacer des pointeurs comme vous le faites en C ou C ++ peut être beaucoup plus rapide.

Giorgio
la source
Notes intéressantes (et lien) sur la manipulation / la traversée de graphes dans un monde purement fonctionnel. Je n'avais pas pensé à ça.
Demian Brecht
7
Les algorithmes de graphes purement fonctionnels sont un sujet intéressant. La solution idiomatique consiste à émuler la représentation impérative en remplaçant les pointeurs par des dictionnaires purement fonctionnels, par exemple en mappant un sommet donné sur l'ensemble des sommets sur lesquels il a des arêtes. Cependant, à moins qu'un dictionnaire faible ne soit utilisé, cela entraînera une perte de mémoire car les sous-graphiques inaccessibles ne peuvent pas être collectés et il n'existe aucun dictionnaire faible purement fonctionnel connu. En fin de compte, une solution à la pointe de la technologie, purement fonctionnelle, est à la fois beaucoup plus compliquée et beaucoup moins efficace!
Jon Harrop
1
Par contre, les algorithmes de graphes peuvent être notoirement difficiles à déboguer et la structure de données persistante peut atténuer ce problème ...
Jon Harrop
Je me demandais s'il serait possible de développer un type de données graphique (suivant l'idée de ByteString: représentation interne efficace plus fonctions de conversion / d'accès). En utilisant des monades, il devrait être possible de rendre de tels graphiques mutables. Bien sûr, cela permettrait de représenter les graphes mais pas de mettre en œuvre des algorithmes de graphes.
Giorgio
Les DAG sont une chose. Pour tout le reste, vous pouvez exploiter la paresse et "faire le noeud".
danielm
4

Le seul inconvénient de Haskell est que c'est différent. C’est un pas en avant par rapport aux langues qui sont plus couramment enseignées ou parlées, ce qui entraîne une courbe d’apprentissage plus longue. C'est également un langage moins populaire qui peut limiter la disponibilité de l'aide si vous êtes bloqué. Ce ne sont pas vraiment des inconvénients majeurs cependant.

L'inconvénient potentiel est qu'il s'agit d'un langage fonctionnel, ce qui le rend moins utile pour certains domaines problématiques, mais cela vaut également pour les langages orientés objet. En général, les langues ne présentent pas de véritables négatifs au-delà des courbes d'apprentissage, du moins pour les langues relativement populaires. Tant qu'une langue est complète, elle est théoriquement capable de tout.

Ryathal
la source
3
La complétude turing est un hareng rouge. Théorie du calcul! = Programmation pratique.
1
@delnan c'est pourquoi j'ai dit théoriquement
Ryathal
2
Quels sont ces "domaines problématiques" pour lesquels Haskell serait prétendument moins utile?
Andres F.
3
S'il est vrai que la communauté est plus petite , elle est en fait disproportionnée. Je pense que la chaîne #haskell sur freenode est seulement derrière la popularité de #python dans les chaînes de langue, et répondre aux questions sur Haskell sur SO est étonnamment compétitif :)
Tikhon Jelvis
@AndresF. - Je n'irais pas jusqu'à dire "moins utile", mais voici quelques domaines dans lesquels Haskell en est encore à ses balbutiements: 1) le DP lourd - J'ai codé un algorithme de sac à dos simple, et j'ai été littéralement choqué par la c'était lent. C'était en utilisant des tableaux en boîte, donc je m'attendais à des frais généraux, mais c'était bien pire que prévu. 2) les grands jeux non triviaux - le PRPA en est à ses balbutiements; il n’existe donc pas de cadre particulièrement performant et la performance est encore trop difficile à prévoir. Il faudra longtemps avant de voir la version Haskell de Doom. (frag ne compte pas - il n'a pas d'
intelligence
0

Donc, étant donné cela, ce que je recherche, ce sont les inconvénients ou les problèmes qui viennent avec Haskell.

Les "problèmes avec Haskell" ont tendance à apparaître dans certains domaines. Haskell est un langage merveilleux pour la programmation d'applications, bien plus agréable à écrire que n'importe quoi d'autre. Les problèmes ont tendance à surgir lorsque vous essayez de faire quelque chose pour lequel il n’ya pas de soutien, comme:

  • Cross compilation. GHC peut être construit en tant que compilateur croisé, mais le processus est plutôt impliqué.
  • Applications embarquées. Haskell a la gestion de la mémoire via un ramasse-miettes, donc celui-ci n'est pas trop surprenant.
  • La vitesse. Haskell n’est pas aussi rapide que Rust, bien que dans la plupart des cas, la concurrence soit assez bonne. Cela dépend beaucoup du domaine d'application - les calculs purs sont bien optimisés, mais quelque chose comme "lire un fichier dans un tampon et compter le nombre de lignes" est plus difficile à exprimer en Haskell.

la source