Quel est le problème avec Haskell? [fermé]

109

Je connais quelques programmeurs qui n'arrêtent pas de parler d'Haskell lorsqu'ils sont entre eux, et ici, tout le monde semble aimer ce langage. Être bon chez Haskell semble un peu comme la marque d'un programmeur de génie.

Quelqu'un peut-il donner quelques exemples Haskell qui montrent pourquoi il est si élégant / supérieur?

Frank
la source

Réponses:

134

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!

Edward Z. Yang
la source
47
Il convient de noter que les messages d'erreur de Haskell ne manquent pas, mais ceux de ghc. La norme Haskell ne spécifie pas comment les messages d'erreur sont générés.
PyRulez
Pour la plèbe comme moi, GHC signifie Glasgow Haskell Compiler. en.wikipedia.org/wiki/Glasgow_Haskell_Compiler
Lorem Ipsum
137

C'est l' exemple qui m'a convaincu d'apprendre Haskell (et je suis content de l'avoir fait).

-- program to copy a file --
import System.Environment

main = do
         --read command-line arguments
         [file1, file2] <- getArgs

         --copy file contents
         str <- readFile file1
         writeFile file2 str

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 lewriteFile 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 writeFiledé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 courirstrace 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:

  1. Meilleure conception du programme. Une complexité réduite entraîne moins d'erreurs logiques.

  2. Code compact. Moins de lignes sur lesquelles les bogues existent.

  3. 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.

Artelius
la source
Comment changeriez-vous exactement la constante de 8 Ko (ou quoi que ce soit)? Parce que je parierais qu'une implémentation Haskell serait plus lente qu'une version C sinon, surtout sans prélecture ...
user541686
1
@Mehrdad Vous pouvez modifier la taille de la mémoire tampon avec hSetBuffering handle (BlockBuffering (Just bufferSize)).
David
3
Il est étonnant que cette réponse contienne 116 votes positifs, mais ce qui s'y trouve est tout simplement faux. Ce programme va lire le fichier entier, sauf si vous utilisez paresseux (que des chaînes ordinaires que vous pouvez faire avec 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.
Jo So
14
L'ancienne norme ennuyeuse readFilefait également des E / S paresseuses de la même manière Data.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 : "La readFilefonction lit un fichier et renvoie le contenu du fichier sous forme de chaîne. Le fichier est lu paresseusement, à la demande, comme avec getContents."
Daniel Wagner
1
Je pense que les autres réponses indiquent des choses qui sont plus spéciales chez Haskell. De nombreuses langues / environnements ont cours d' eau, vous pouvez faire quelque chose de similaire dans le nœud: 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
Max Heiber
64

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:

  • Évaluation paresseuse
  • Pas d'effets secondaires (tout est pur, IO / etc se passe via des monades)
  • Système de type statique incroyablement expressif

ainsi que d'autres aspects différents de ceux de nombreuses langues traditionnelles (mais partagés par certains):

  • fonctionnel
  • espace blanc significatif
  • type inféré

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.)

Brian
la source
17
Je ne suis pas d'accord avec votre première phrase. J'ai été vraiment impressionné par quelques exemples de code Haskell au départ et ce qui m'a vraiment convaincu qu'il valait la peine d'apprendre était cet article: cs.dartmouth.edu/~doug/powser.html Mais bien sûr, c'est intéressant pour un mathématicien / physicien. Un programmeur qui regarde des choses du monde réel trouverait cet exemple ridicule.
Rafael S. Calsaverini
2
@Rafael: Cela soulève la question "par quoi un programmeur qui s'intéresse aux choses du monde réel serait-il impressionné"?
JD
Bonne question! Je ne suis pas un programmeur "du monde réel" donc je ne sais pas ce qu'ils aiment. hahaha ... Je sais ce que les physiciens et les mathématiciens aiment. : P
Rafael S. Calsaverini
27

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é.

gtd
la source
1
Eh bien, il y a toujours la possibilité d'utiliser toujours et uniquement la monade ST et / ou unsafePerformIOpour les personnes qui veulent juste regarder le monde brûler;)
sara
22

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 .

Don Stewart
la source
"avec un compilateur de code natif rapide"?
JD
Je crois que dons fait référence à GHCI.
Gregory Higley
3
@Jon: shootout.alioth.debian.org/u32/… Haskell fait plutôt bien sur la fusillade, par exemple.
Peaker
4
@Jon: Le code de fusillade est très ancien, et provient d'un passé lointain où GHC était moins un compilateur d'optimisation. Pourtant, cela prouve que le code Haskell peut aller de bas niveau pour générer des performances, si nécessaire. Les nouvelles solutions dans la fusillade sont plus idiomatiques et toujours rapides.
Peaker
1
@GregoryHigley Il y a une différence entre GHCI et GHC.
Jeremy List
18

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.

bmdhacks
la source
18

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

c1 `mappend` c2 `mappend` c3

c1et ainsi de suite LT, EQou GT, c1renvoyer EQfait continuer l'expression, en évaluant c2; si c2retourne LTou GTc'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.

Curt J.Sampson
la source
2
Très intéressant! Combien de lignes de code Haskell sont entrées dans votre système de trading automatisé au total? Comment avez-vous géré la tolérance aux pannes et quels types de résultats de performance avez-vous obtenus? J'ai pensé récemment que Haskell a le potentiel d'être bon pour la programmation à faible latence ...
JD
12

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.

James Black
la source
2
la récursivité est la bombe. cela et la correspondance de modèle.
Ellery Newcomer le
1
Se débarrasser des boucles for et while est la partie la plus difficile pour moi lorsque j'écris dans un langage fonctionnel. :)
James Black
4
Apprendre à penser en récursivité au lieu de boucles a été la partie la plus difficile pour moi aussi. Quand il a finalement coulé, c'était l'une des plus grandes épiphanies de programmation que j'aie jamais eues.
Chris Connett
8
Sauf que le programmeur Haskell qui travaille utilise rarement la récursivité primitive; vous utilisez principalement des fonctions de bibliothèque comme map et foldr.
Paul Johnson
18
Je trouve plus intéressant que l'algorithme de tri rapide original de Hoare ait été bâti dans cette forme basée sur une liste déplacée apparemment pour que des implémentations inefficaces puissent être écrites "élégamment" en Haskell. Si vous essayez d'écrire un vrai tri rapide (sur place) dans Haskell, vous trouverez que c'est moche comme l'enfer. Si vous essayez d'écrire un tri rapide générique compétitif dans Haskell, vous constaterez qu'il est en fait impossible en raison de bogues de longue date dans le ramasse-miettes de GHC. Saluant quicksort comme un bon exemple pour la croyance des mendiants Haskell, à mon humble avis.
JD
8

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é.

maxaposteriori
la source
1
N'oubliez pas de lire le code source du compilateur. Cela vous donnera également beaucoup d'informations précieuses.
JD
7

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

primes = sieve [2..]
    where sieve (p:xs) = p : sieve [x | x<-xs, x `mod` p /= 0]

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:

foo = sum $ takeWhile (<100) primes

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.

waxwing
la source
2
Ce n'est pas entièrement vrai; avec le comportement de retour de rendement de C # (un langage orienté objet), vous pouvez également déclarer des listes infinies qui sont évaluées à la demande.
Jeff Yates
2
Bon point. Vous avez raison et je devrais éviter de dire ce qui peut et ne peut pas être fait dans d’autres langues de manière aussi catégorique. Je pense que mon exemple était imparfait, mais je pense quand même que vous gagnez quelque chose de la méthode d'évaluation paresseuse de Haskell: c'est vraiment là par défaut et sans aucun effort du programmeur. Et cela, je crois, est dû à sa nature fonctionnelle et à l'absence d'effets secondaires.
waxwing le
8
Vous serez peut-être intéressé de savoir pourquoi «tamis» n'est pas le tamis d'Eratosthène: lambda-the-ultimate.org/node/3127
Chris Conway
@Chris: Merci, c'était en fait un article assez intéressant! La fonction nombres premiers ci-dessus n'est pas celle que j'ai utilisée pour mes propres calculs car elle est extrêmement lente. Néanmoins, l'article soulève un bon point que la vérification de tous les nombres pour le mod est vraiment un algorithme différent.
waxwing
6

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:

bottomUp :: (Ord a, Num a) => [[a]] -> a
bottomUp = head . bu
  where bu [bottom]     = bottom
        bu (row : base) = merge row $ bu base
        merge [] [_] = []
        merge (x:xs) (y1:y2:ys) = x + max y1 y2 : merge xs (y2:ys)

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:

data BubbleResult i o = BubbleResult { bestResult :: o
                                     , result :: o
                                     , leftoverRandoms :: [Double]
                                     }
bubbleSearch :: (Ord result) =>
                ([a] -> result) ->       -- greedy search algorithm
                Double ->                -- probability
                [a] ->                   -- list of items to be searched
                [Double] ->              -- list of random numbers
                [BubbleResult a result]  -- monotone list of results
bubbleSearch search p startOrder rs = bubble startOrder rs
    where bubble order rs = BubbleResult answer answer rs : walk tries
            where answer = search order
                  tries  = perturbations p order rs
                  walk ((order, rs) : rest) =
                      if result > answer then bubble order rs
                      else BubbleResult answer result rs : walk rest
                    where result = search order

perturbations :: Double -> [a] -> [Double] -> [([a], [Double])]
perturbations p xs rs = xr' : perturbations p xs (snd xr')
    where xr' = perturb xs rs
          perturb :: [a] -> [Double] -> ([a], [Double])
          perturb xs rs = shift_all p [] xs rs

shift_all p new' [] rs = (reverse new', rs)
shift_all p new' old rs = shift_one new' old rs (shift_all p)
  where shift_one :: [a] -> [a] -> [Double] -> ([a]->[a]->[Double]->b) -> b
        shift_one new' xs rs k = shift new' [] xs rs
          where shift new' prev' [x] rs = k (x:new') (reverse prev') rs
                shift new' prev' (x:xs) (r:rs) 
                    | r <= p    = k (x:new') (prev' `revApp` xs) rs
                    | otherwise = shift new' (x:prev') xs rs
                revApp xs ys = foldl (flip (:)) ys xs

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.

Norman Ramsey
la source
5

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.

rpg
la source
6
Comment garantit-il l'exactitude?
Jonathan Fischoff
Les parties pures du code sont beaucoup plus sûres que les impures. Le niveau de confiance / d'effort investi est bien plus élevé.
rpg
1
Qu'est-ce qui vous a donné cette impression?
JD
5

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:

toto a = a + 5

C'est la manière la plus simple que je puisse imaginer de définir une fonction.

Si j'écris l'inverse

inverseFoo a = a - 5

Je peux vérifier qu'il s'agit d'un inverse pour toute entrée aléatoire en écrivant

prop_IsInverse :: Double -> Bool
prop_IsInverse a = a == (inverseFoo $ foo a)

Et appeler depuis la ligne de commande

jonny @ ubuntu: runhaskell quickCheck + noms fooFileName.hs

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.

Jonathan Fischoff
la source
Quels problèmes résolvez-vous et quelles autres langues avez-vous essayées?
JD
1
Graphiques 3D en temps réel pour le mobile et l'iPad.
Jonathan Fischoff
3

Si vous pouvez comprendre le système de typage dans Haskell, je pense que c'est en soi un accomplissement.

Dr Watson
la source
1
Qu'y a-t-il à obtenir? Si vous devez, pensez "data" == "class" et "typeclass" = "interface" / "role" / "trait". Cela ne pouvait pas être plus simple. (Il n'y a même pas de "null" pour vous gâcher. Null est un concept que vous pouvez
intégrer
8
Il y a beaucoup à obtenir, jrockway. Bien que vous et moi trouviez cela relativement simple, beaucoup de gens - même de nombreux développeurs - trouvent certains types d'abstractions très difficiles à comprendre. Je connais de nombreux développeurs qui ne comprennent toujours pas tout à fait l'idée de pointeurs et de références dans des langages plus courants, même s'ils les utilisent tous les jours.
Gregory Higley
2

il n'a pas de constructions de boucle. peu de langues ont ce trait.

Badri
la source
17
ghci>: m + Control.Monad ghci> forM_ [1..3] print 1 2 3
sastanin
1

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).

Jacob
la source
-1

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 :

HM est très joli, dans un sens mathématique formel totalement inutile. Il gère très bien quelques constructions de calcul; la répartition de correspondance de modèle trouvée dans Haskell, SML et OCaml est particulièrement pratique. Sans surprise, il gère au mieux d'autres constructions courantes et hautement souhaitables, mais ils expliquent ces scénarios en disant que vous vous trompez, que vous ne les voulez pas vraiment. Vous savez, des choses comme, oh, définir des variables.

Haskell vaut la peine d'être appris, mais il a ses propres faiblesses.

RossFabricant
la source
5
S'il est certainement vrai que les systèmes de type forts exigent généralement que vous y adhériez (c'est ce qui rend leur force utile), il est également vrai que de nombreux systèmes de type HM existants (la plupart?) Ont, en fait, une sorte de ' escape hatch 'comme décrit dans le lien (prenez Obj.magic dans O'Caml comme exemple, bien que je ne l'ai jamais utilisé sauf comme un hack); en pratique, cependant, pour de nombreux types de programmes, on n'a jamais besoin d'un tel appareil.
Zach Snow
3
La question de savoir si l'établissement de variables est «souhaitable» dépend de la difficulté d'utiliser les constructions alternatives par rapport à la douleur causée par l'utilisation des variables. Ce n'est pas pour écarter tout l'argument, mais plutôt pour souligner que prendre l'énoncé "les variables sont une construction hautement souhaitable" comme un axiome n'est pas la base d'un argument convaincant. Il se trouve que c'est la façon dont la plupart des gens apprennent à programmer.
gtd
5
-1: Les déclarations de Steve sont en partie obsolètes mais la plupart du temps complètement fausses. La restriction de valeur assouplie d'OCaml et le système de types de .NET sont des contre-exemples évidents à ses déclarations.
JD
4
Steve Yegge a une abeille déraisonnable dans son bonnet à propos de la frappe statique, et non seulement la plupart de ce qu'il dit à ce sujet est faux, mais il continue également à en parler à chaque occasion disponible (et même certaines non disponibles). Vous feriez bien de ne faire confiance qu'à votre propre expérience à cet égard.
ShreevatsaR
3
Bien que je ne sois pas d'accord avec Yegge sur le typage statique ou dynamique, Haskell a le type Data.Dynamic. Si vous voulez une saisie dynamique, vous pouvez l'avoir!
jrockway le