La façon dont cela m'a été présenté, et ce que je pense être vrai après avoir travaillé sur l'apprentissage sur Haskell pendant un mois maintenant, c'est le fait que la programmation fonctionnelle tord votre cerveau de manière intéressante: cela vous oblige à penser à des problèmes familiers de différentes manières. : au lieu de boucles, pensez aux cartes, aux plis et aux filtres, etc. En général, si vous avez plus d'une perspective sur un problème, cela vous permet de mieux raisonner sur ce problème et de changer de point de vue si nécessaire.
L'autre chose vraiment intéressante à propos de Haskell est son système de types. Il est strictement typé, mais le moteur d'inférence de type donne l'impression d'être un programme Python qui vous indique comme par magie lorsque vous avez commis une erreur de type stupide. Les messages d'erreur de Haskell à cet égard font quelque peu défaut, mais à mesure que vous vous familiariserez avec le langage, vous vous direz: c'est ce que la frappe est censée être!
C'est l' exemple qui m'a convaincu d'apprendre Haskell (et je suis content de l'avoir fait).
OK, c'est un programme court et lisible. En ce sens, c'est mieux qu'un programme C. Mais en quoi est-ce si différent (disons) d'un programme Python avec une structure très similaire?
La réponse est une évaluation paresseuse. Dans la plupart des langages (même certains fonctionnels), un programme structuré comme celui ci-dessus entraînerait le chargement du fichier entier en mémoire, puis réécrit sous un nouveau nom.
Haskell est "paresseux". Il ne calcule pas les choses avant d'en avoir besoin et, par extension, ne calcule pas les choses dont il n'a jamais besoin. Par exemple, si vous supprimez le
writeFile
ligne, Haskell ne prendrait pas la peine de lire quoi que ce soit du fichier en premier lieu.Dans l'état actuel des choses, Haskell se rend compte que le
writeFile
dépend de lareadFile
, et peut donc optimiser ce chemin de données.Bien que les résultats dépendent du compilateur, ce qui se passera généralement lorsque vous exécuterez le programme ci-dessus est le suivant: le programme lit un bloc (disons 8 Ko) du premier fichier, puis l'écrit dans le deuxième fichier, puis lit un autre bloc à partir du premier fichier et l'écrit dans le deuxième fichier, et ainsi de suite. (Essayez de courir
strace
dessus!)... qui ressemble beaucoup à ce que ferait l'implémentation C efficace d'une copie de fichier.
Ainsi, Haskell vous permet d'écrire des programmes compacts et lisibles - souvent sans sacrifier beaucoup de performances.
Une autre chose que je dois ajouter est que Haskell rend simplement difficile l'écriture de programmes bogués. Le système de type étonnant, le manque d'effets secondaires et bien sûr la compacité du code Haskell réduisent les bogues pour au moins trois raisons:
Meilleure conception du programme. Une complexité réduite entraîne moins d'erreurs logiques.
Code compact. Moins de lignes sur lesquelles les bogues existent.
Compilez les erreurs. Beaucoup de bugs ne sont tout simplement pas valides Haskell .
Haskell n'est pas pour tout le monde. Mais tout le monde devrait essayer.
la source
hSetBuffering handle (BlockBuffering (Just bufferSize))
.Data.Bytestring.Lazy.readFile
), qui n'a rien à voir avec Haskell étant une langue paresseuse (non stricte). Les monades sont séquencées - cela signifie à peu près "tous les effets secondaires sont terminés lorsque vous supprimez le résultat". Quant à la magie du "lazy Bytestring": c'est dangereux, et vous pouvez le faire avec une syntaxe similaire ou plus simple dans la plupart des autres langages.readFile
fait également des E / S paresseuses de la même manièreData.ByteString.Lazy.readFile
. La réponse n'est donc pas fausse, et ce n'est pas simplement une optimisation du compilateur. En effet, cela fait partie de la spécification d'Haskell : "LareadFile
fonction lit un fichier et renvoie le contenu du fichier sous forme de chaîne. Le fichier est lu paresseusement, à la demande, comme avecgetContents
."const fs = require('fs'); const [file1, file2] = process.argv.slice(2); fs.createReadStream(file1).pipe(fs.createWriteStream(file2))
. Bash a aussi quelque chose de similaire:cat $1 > $2
Vous posez en quelque sorte la mauvaise question.
Haskell n'est pas un langage où vous allez regarder quelques exemples sympas et dire "aha, je vois maintenant, c'est ce qui fait du bien!"
C'est plutôt, nous avons tous ces autres langages de programmation, et ils sont tous plus ou moins similaires, et puis il y a Haskell qui est totalement différent et farfelu d'une manière totalement géniale une fois que vous vous êtes habitué à la folie. Mais le problème est qu'il faut un certain temps pour s'acclimater à la folie. Ce qui distingue Haskell de presque tous les autres langages, même semi-traditionnels:
ainsi que d'autres aspects différents de ceux de nombreuses langues traditionnelles (mais partagés par certains):
Comme l'ont répondu d'autres affiches, la combinaison de toutes ces fonctionnalités signifie que vous pensez à la programmation d'une manière totalement différente. Et il est donc difficile de trouver un exemple (ou un ensemble d'exemples) qui communique correctement cela à Joe-mainstream-programmeur. C'est une chose expérientielle. (Pour faire une analogie, je peux vous montrer des photos de mon voyage en Chine en 1970, mais après avoir vu les photos, vous ne saurez toujours pas ce que c'était que d'avoir vécu là-bas pendant cette période. De même, je peux vous montrer un Haskell 'quicksort', mais vous ne saurez toujours pas ce que signifie être un Haskeller.)
la source
Ce qui distingue vraiment Haskell, c'est l'effort qu'il déploie dans sa conception pour appliquer la programmation fonctionnelle. Vous pouvez programmer dans un style fonctionnel dans à peu près n'importe quelle langue, mais c'est trop facile à abandonner à la première convenance. Haskell ne vous permet pas d'abandonner la programmation fonctionnelle, vous devez donc la mener à sa conclusion logique, qui est un programme final sur lequel il est plus facile de raisonner, et évite toute une classe des types de bogues les plus épineux.
Quand il s'agit d'écrire un programme pour une utilisation dans le monde réel, vous pouvez trouver Haskell manquant d'une manière pratique, mais votre solution finale sera meilleure pour avoir connu Haskell pour commencer. Je n'y suis certainement pas encore, mais jusqu'à présent, apprendre Haskell a été beaucoup plus éclairant que de dire que Lisp était à l'université.
la source
unsafePerformIO
pour les personnes qui veulent juste regarder le monde brûler;)Une partie de l'agitation est que la pureté et le typage statique permettent un parallélisme combiné à des optimisations agressives. Les langages parallèles sont chauds maintenant, le multicœur étant un peu perturbateur.
Haskell vous offre plus d'options pour le parallélisme que pratiquement n'importe quel langage à usage général, ainsi qu'un compilateur de code natif rapide. Il n'y a vraiment aucune concurrence avec ce type de support pour les styles parallèles:
Donc, si vous vous souciez de faire fonctionner votre multicœur, Haskell a quelque chose à dire. Un bon point de départ est le tutoriel de Simon Peyton Jones sur la programmation parallèle et simultanée dans Haskell .
la source
La mémoire transactionnelle logicielle est un moyen assez cool de gérer la concurrence. C'est beaucoup plus flexible que la transmission de messages, et pas enclin à une impasse comme les mutex. La mise en œuvre de la STM par GHC est considérée comme l'une des meilleures.
la source
J'ai passé la dernière année à apprendre Haskell et à écrire un projet assez vaste et complexe. (Le projet est un système de trading d'options automatisé, et tout, des algorithmes de trading à l'analyse et à la gestion des flux de données de marché de bas niveau et à haute vitesse, est effectué dans Haskell.) C'est beaucoup plus concis et plus facile à comprendre (pour ceux qui ont arrière-plan approprié) qu'une version Java serait, ainsi que extrêmement robuste.
La plus grande victoire pour moi a probablement été la possibilité de modulariser le flux de contrôle à travers des éléments tels que les monoïdes, les monades, etc. Un exemple très simple serait le monoïde Ordering; dans une expression telle que
où
c1
et ainsi de suiteLT
,EQ
ouGT
,c1
renvoyerEQ
fait continuer l'expression, en évaluantc2
; sic2
retourneLT
ouGT
c'est la valeur du tout, etc3
n'est pas évalué. Ce genre de chose devient considérablement plus sophistiqué et complexe dans des choses comme les générateurs et analyseurs de messages monadiques où je peux transporter différents types d'état, avoir des conditions d'abandon variables ou vouloir être en mesure de décider pour un appel particulier si abandonner signifie vraiment "aucun traitement supplémentaire" ou signifie "renvoyer une erreur à la fin, mais poursuivre le traitement pour collecter d'autres messages d'erreur".C'est tout ce qu'il faut du temps et probablement pas mal d'efforts pour apprendre, et il peut donc être difficile de faire un argument convaincant pour ceux qui ne connaissent pas déjà ces techniques. Je pense que le tout sur les monades didacticiel donne une démonstration assez impressionnante d'une facette de ceci, mais je ne m'attendrais pas à ce que quelqu'un qui ne soit pas déjà familier avec le matériel le «comprenne» dès la première, voire la troisième, lecture attentive.
Quoi qu'il en soit, il y a aussi beaucoup d'autres bonnes choses dans Haskell, mais c'est une question majeure que je ne vois pas si souvent mentionnée, probablement parce que c'est plutôt complexe.
la source
Pour un exemple intéressant, vous pouvez consulter: http://en.literateprograms.org/Quicksort_(Haskell)
Ce qui est intéressant, c'est de regarder l'implémentation dans différentes langues.
Ce qui rend Haskell si intéressant, avec d'autres langages fonctionnels, c'est le fait que vous devez penser différemment à la façon de programmer. Par exemple, vous n'utiliserez généralement pas de boucles for ou while, mais utiliserez la récursivité.
Comme mentionné ci-dessus, Haskell et d'autres langages fonctionnels excellent avec des applications de traitement et d'écriture parallèles pour travailler sur des multi-cœurs.
la source
Je ne pourrais pas vous donner d'exemple, je suis un gars d'OCaml, mais quand je suis dans une situation comme vous-même, la curiosité s'installe et je dois télécharger un compilateur / interprète et essayer. Vous en apprendrez probablement beaucoup plus de cette façon sur les forces et les faiblesses d'un langage fonctionnel donné.
la source
Une chose que je trouve très cool quand on traite des algorithmes ou des problèmes mathématiques est l'évaluation paresseuse inhérente de Haskell des calculs, qui n'est possible qu'en raison de sa nature fonctionnelle stricte.
Par exemple, si vous souhaitez calculer tous les nombres premiers, vous pouvez utiliser
et le résultat est en fait une liste infinie. Mais Haskell l'évaluera de gauche à droite, donc tant que vous n'essayez pas de faire quelque chose qui nécessite la liste entière, vous pouvez toujours l'utiliser sans que le programme reste bloqué à l'infini, comme:
qui somme tous les nombres premiers inférieurs à 100. C'est bien pour plusieurs raisons. Tout d'abord, je n'ai besoin d'écrire qu'une seule fonction première qui génère tous les nombres premiers, puis je suis à peu près prêt à travailler avec les nombres premiers. Dans un langage de programmation orienté objet, j'aurais besoin d'un moyen de dire à la fonction combien de nombres premiers elle doit calculer avant de retourner, ou d'émuler le comportement de la liste infinie avec un objet. Une autre chose est qu'en général, vous finissez par écrire du code qui exprime ce que vous voulez calculer et non dans quel ordre évaluer les choses - au lieu de cela, le compilateur le fait pour vous.
Ce n'est pas seulement utile pour les listes infinies, en fait, il est utilisé sans que vous le sachiez tout le temps quand il n'est pas nécessaire d'évaluer plus que nécessaire.
la source
Je suis d'accord avec d'autres pour dire que voir quelques petits exemples n'est pas la meilleure façon de montrer Haskell. Mais je vais quand même en donner. Voici une solution ultra-rapide aux problèmes 18 et 67 du projet Euler , qui vous demandent de trouver le chemin de somme maximale de la base au sommet d'un triangle:
Voici une implémentation complète et réutilisable de l' algorithme BubbleSearch par Lesh et Mitzenmacher. Je l'ai utilisé pour emballer de gros fichiers multimédias pour le stockage d'archives sur DVD sans gaspillage:
Je suis sûr que ce code ressemble à du charabia aléatoire. Mais si vous lisez l'entrée de blog de Mitzenmacher et comprenez l'algorithme, vous serez étonné qu'il soit possible de conditionner l'algorithme dans du code sans rien dire sur ce que vous recherchez.
Après vous avoir donné quelques exemples comme vous l'avez demandé, je dirai que le meilleure façon de commencer à apprécier Haskell est de lire l'article qui m'a donné les idées dont j'avais besoin pour écrire le packer de DVD: Why Functional Programming Matters de John Hughes. Le document est en fait antérieur à Haskell, mais il explique avec brio certaines des idées qui font que les gens aiment Haskell.
la source
Pour moi, l'attrait de Haskell est la promesse d' une correction garantie du compilateur . Même si c'est pour des parties pures du code.
J'ai écrit beaucoup de code de simulation scientifique et je me suis demandé tant de fois s'il y avait un bogue dans mes codes précédents, ce qui pourrait invalider beaucoup de travaux actuels.
la source
Je trouve que pour certaines tâches, je suis incroyablement productif avec Haskell.
La raison en est la syntaxe succincte et la facilité des tests.
Voici à quoi ressemble la syntaxe de déclaration de fonction:
C'est la manière la plus simple que je puisse imaginer de définir une fonction.
Si j'écris l'inverse
Je peux vérifier qu'il s'agit d'un inverse pour toute entrée aléatoire en écrivant
Et appeler depuis la ligne de commande
Ce qui vérifiera que toutes les propriétés de mon fichier sont conservées, en testant aléatoirement les entrées une centaine de fois.
Je ne pense pas que Haskell soit le langage parfait pour tout, mais quand il s'agit d'écrire de petites fonctions et de tester, je n'ai rien vu de mieux. Si votre programmation a une composante mathématique, c'est très important.
la source
Si vous pouvez comprendre le système de typage dans Haskell, je pense que c'est en soi un accomplissement.
la source
il n'a pas de constructions de boucle. peu de langues ont ce trait.
la source
Je suis d'accord avec ceux qui ont dit que la programmation fonctionnelle tord votre cerveau pour voir la programmation sous un angle différent. Je ne l'ai utilisé qu'en tant qu'amateur, mais je pense que cela a fondamentalement changé ma façon d'aborder un problème. Je ne pense pas que j'aurais été presque aussi efficace avec LINQ sans avoir été exposé à Haskell (et en utilisant des générateurs et des listes de compréhension en Python).
la source
Pour diffuser une vision contraire: Steve Yegge écrit que les langages Hindely-Milner manquent de la flexibilité nécessaire pour écrire de bons systèmes :
Haskell vaut la peine d'être appris, mais il a ses propres faiblesses.
la source