Pourquoi la syntaxe du langage fonctionnel n'est-elle pas plus proche du langage humain?


14

Je suis intéressé par la programmation fonctionnelle et j'ai décidé de me confronter à Haskell. Ma tête me fait mal ... mais je finirai par l'obtenir ... J'ai une curiosité cependant, pourquoi la syntaxe est-elle si cryptique (en l'absence d'un autre mot)?

Y a-t-il une raison pour laquelle il n'est pas plus expressif , plus proche du langage humain?

Je comprends que FP est bon en modélisation de concepts mathématiques et il a emprunté certains de ses moyens d'expression concis, mais ce n'est toujours pas des mathématiques ... c'est un langage.


4
@ratchet freak: :) alors y en a-t-il un conçu par un gars qui déteste la notation polonaise?
JohnDoDo

10
@ratchetfreak En quoi la syntaxe Haskell ressemble-t-elle à la notation polonaise? Les opérateurs Haskell sont des infixes, tout comme la plupart des opérateurs des autres langues (et les appels de fonction sont des préfixes - également comme la plupart des appels de fonction des autres langues).
sepp2k

9
C'est une supposition / saut assez important que vous faites, que "plus proche du langage humain" équivaut à "plus expressif".
Matt Ball

7
Avez-vous déjà entendu parler de Cobol et Fortran?
ott--

7
Pour la même raison que les mathématiciens ont remplacé les longues phrases latines par des expressions algébriques. Avec un peu de pratique, une notation plus compacte est beaucoup plus productive.
kevin cline

Réponses:


14

Les langages fonctionnels comme Haskell et son antécédent Miranda sont nés du concept mathématique du calcul lambda . Depuis la page Wikipedia:

Le calcul lambda (également écrit sous le nom de λ-calcul ou appelé "le calcul lambda") est un système formel en logique mathématique pour exprimer le calcul au moyen d'une liaison et d'une substitution de variable.

...

Le calcul lambda a joué un rôle important dans le développement de la théorie des langages de programmation. Les équivalents les plus importants du calcul lambda en informatique sont les langages de programmation fonctionnels, qui implémentent essentiellement le calcul (augmenté de quelques constantes et types de données). Au-delà des langages de programmation, le calcul lambda a également de nombreuses applications en théorie de la preuve. Un exemple majeur de ceci est la correspondance Curry-Howard, qui donne une correspondance entre différents systèmes de calcul lambda typé et des systèmes de logique formelle.

En raison de cette histoire, les syntaxes de ces langages fonctionnels (et des éléments fonctionnels des langages plus impératifs) sont fortement influencées par la notation mathématique utilisée par le calcul lambda.

La précision avec laquelle les notations mathématiques et les langages informatiques peuvent décrire les exigences et la précision avec laquelle les ordinateurs exigent que leurs instructions soient écrites sont bien corrélées entre elles. L'imprécision du langage naturel crée cependant un énorme obstacle à son utilisation pour la programmation des ordinateurs. Même les environnements de programmation en langage naturel les plus réussis (sans doute) tels que Wolfram Alpha nécessitent une expérience de domaine significative pour être utilisés efficacement.


29

La syntaxe Haskell est proche du langage humain. Il est spécifiquement conçu pour ressembler à la notation mathématique, qui est un langage conçu par les humains (donc un langage humain ) pour exprimer précisément les concepts sur lesquels Haskell est construit.

Vous pouvez montrer un morceau de code Haskell à n'importe quel mathématicien ou logicien, et il pourra le comprendre, même s'il n'a jamais entendu parler de Haskell et ne sait absolument rien de la programmation, de l'informatique ou même des ordinateurs.

D'un autre côté, vous pouvez montrer à n'importe quel mathématicien ou logicien un morceau de code comme celui-ci:

x = x + 1

et il sera complètement confus, en disant: "Cela n'a pas de sens, il n'y en a pas xqui xsoit égal à xplus 1."

Qu'une notation spécifique soit ou non «cryptique» est une question d'opinion et de familiarité.


8
Il y a juste un problème avec cette réponse: je ne suis pas mathématicien.
JohnDoDo

6
@ sepp2k: je ne suis pas d'accord. Pour la plupart des gens sans exposition préalable aux langages de programmation et à certains antécédents mathématiques de base, la syntaxe Haskell sera beaucoup plus simple à comprendre que le code procédural typique avec tous ses effets secondaires et les instructions d'environnements compliqués qui sont exécutées. La syntaxe comme wherepermet de condenser l'essentiel de une fonction sur une seule ligne.
Benjamin Bannier

17
-1: cette réponse semble largement pédante. Je suis assez certain que l'OP signifiait la langue parlée.
Steven Evers

6
En fait, je suis presque sûr que x = infinitycela résout bien l'équation.
DeadMG

6
Eh bien, les langages de programmation sont également conçus par des humains ... Ainsi, selon votre définition, ce sont des langages humains.
marco-fiset

13

Je pense qu'une chose que vous rencontrez probablement est quelque chose que j'ai rencontré aussi lors de l'apprentissage de la programmation fonctionnelle, c'est qu'avec la programmation fonctionnelle vous pouvez (et presque devez) penser / travailler à un niveau plus élevé que vous ne le faites avec la programmation impérative.

Ce que vous trouvez moins expressif, je pense qu'il est en fait plus expressif: vous n'avez pas besoin d'énoncer chaque petit détail et pouvez faire plus avec moins de code dans la programmation fonctionnelle - il y a plus de puissance dans ce que vous écrivez.

Par exemple, je pourrais écrire impérativement:

for each (Person person in people)
    print(person.name)

qui est totalement lisible en anglais.

Une version Haskell pourrait être (et ce n'est pas Haskell valide, mais c'est juste pour une comparaison syntaxique):

map (print . name) people

ce qui nécessite moins de code et moins de détails - je n'ai pas à décomposer les choses en boucle et ses variables ( for each (...)), la mapfonction s'en charge pour moi.

Travailler à ce niveau peut prendre un certain temps pour s'y habituer. Si cela peut aider, Haskell a probablement été le moment le plus difficile pour moi d'apprendre une nouvelle langue depuis que j'ai commencé la programmation, et je connais> 10 langues (dont Lisp). Cela valait vraiment la peine d'apprendre.


8

Je m'attaque actuellement à Scala en ce moment, donc je peux sympathiser. Au moins avec Scala, je peux revenir à un style impératif lorsque les choses deviennent trop difficiles.

Je pense qu'il y a plusieurs forces en jeu ici:

  • Les concepteurs de langages fonctionnels ont nécessairement une solide formation en mathématiques, ils empruntent donc la notation mathématique qui leur est naturelle.

  • Une plus grande expressivité (c.-à-d. La puissance des déclarations, plutôt que la proximité de l'anglais) de n'importe quelle langue a (IMO) un prix correspondant dans la pente de la courbe d'apprentissage. La concision est une qualité très appréciée à Scala, beaucoup de choses étant facultatives.

  • Les langages fonctionnels font juste les choses très différemment, donc les opérations de base ne correspondent pas aux constructions impératives.


3
J'ajouterais également que souvent les langages fonctionnels peuvent exprimer des concepts d'ordre supérieur, ceux-ci étant plus abstraits, sont plus difficiles à nommer de manière significative
jk.

1
@jk, oui, d'accord! Dans le même temps, c'est pourquoi ils ont une courbe d'apprentissage abrupte pour les programmeurs ayant des antécédents impératifs et peu de mathématiques (comme moi), et pourquoi ils en valent la peine.
Richard Close

3

Si j'ai bien compris votre dernier commentaire, votre question est pourquoi Haskell utilise souvent des opérateurs symboliques dans des endroits où il pourrait également utiliser des mots-clés alphanumériques (ou des noms de fonction)?

En ce qui concerne les mots clés, une réponse serait que les mots clés vous empêchent d'utiliser certains mots comme noms de variables. Par exemple, je suis toujours ennuyé quand je veux appeler mes variables fromet todans une langue où l'un d'eux est un mot-clé - comme en Python.

Une autre raison des opérateurs symboliques en général est la concision. Cela ne s'applique pas vraiment dans vos exemples spécifiques de compréhension de liste ( <-n'est pas plus court que in), mais dans de nombreux cas, c'est le cas.

Encore une autre raison est la lisibilité. Cela peut sembler contre-intuitif car les opérateurs symboliques sont souvent plus difficiles à apprendre car leurs "noms" ne vous disent vraiment rien de ce qu'ils font (alors que le nom d'une fonction le fera généralement), mais une fois que vous savez ce que fait un opérateur donné, les expressions avec des opérateurs symboliques infixes sont souvent plus faciles à analyser pour un humain que celles avec beaucoup d'appels de fonction de préfixe alphanumérique car les opérateurs sont plus facilement distingués visuellement des opérandes de cette façon. Par exemple, la plupart des gens conviendraient que 2 * 3 + 4c'est plus facilement lisible que add (mult 2 3) 4ou add(mult(2, 3), 4).


@PeterTaylor Nope, juste moi d'être stupide ;-) Corrigé maintenant.
sepp2k

3

Les langages informatiques impératifs ne sont généralement pas plus proches des langages naturels que, disons, Haskell.

Cependant, certains sont conçus pour ressembler davantage à l'anglais: Cobol et Hypercard, par exemple. Les leçons que je tirerais de ces exemples sont:

  • la similitude avec les langues naturelles ne semble pas entraîner une amélioration directe de la convivialité
  • émuler des langues naturelles directement peut produire des langages informatiques verbeux et obscurs

Le langage informatique Perl aurait été conçu en gardant à l'esprit certains aspects plus subtils du langage naturel . Je dirais que Perl fait mieux que Cobol ou Hypercard sur la convivialité générale, mais les gens ont des opinions divergentes sur Perl.


3

Je pense que Haskell devient aussi similaire au langage humain que l'on peut obtenir sans introduire une syntaxe folle. Cela va vraiment très loin, par exemple avec la whereclause de reporter une définition et avec la syntaxe de compréhension de liste qui est exactement ce que j'écrirais sur un tableau noir. Il évite également les caractères étrangers comme les accolades et a une utilisation libérale de l'indentation. L'exemple typique est le tri rapide:

qsort [] = []
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
               where lesser = [x | x <- xs, x <= p] 
                     greater = [x | x <- xs, x > p]

Certes, c'est un exemple simple, mais je ne connais aucun autre langage qui le rende aussi lisible.

Faire des choses plus compliquées peut devenir difficile à lire dans Haskell, mais cela a à voir avec le système de type, les entrées-sorties contraintes et pas du tout avec la syntaxe.

Si quoi que ce soit, je dirais que Haskell a sacrifié la simplicité syntaxique afin d'accommoder une syntaxe plus proche du langage humain. Un schéma de type langage a une syntaxe très éloignée de ce qu'un humain écrirait, mais il est vraiment simple d'expliquer ses règles.


3
J'appellerais à peine cela lisible par l'homme. Je connais le tri rapide. Je sais comment le configurer dans plusieurs langues différentes, je sais ce qu'il est censé faire et je ne peux toujours pas faire de têtes ou de queues dans la moitié inférieure de cet extrait de code.
Mason Wheeler

Je suppose que cela dépend vraiment de votre parcours. C'est aussi simple que ça pour moi ...
Andrea

2
Dans tous les cas, il est censé ressembler à cette notation: purplemath.com/modules/setnotn.htm
Andrea

4
Êtes-vous sûr que cela ne devrait pas l'être ++ [p] ++?
Peter Taylor

1
@Mason: Cela me semble assez clair, et je n'ai jamais écrit une ligne de Haskell
kevin cline

2

Je pense que la différence a à voir avec la façon dont la programmation fonctionnelle / déclarative fait des déclarations sur un problème comme s'il s'agissait d'un problème mathématique, alors que la programmation impérative décrit un processus . Dans le monde des affaires, les programmes informatiques enveloppent ou remplacent les processus physiques, vous pouvez donc trouver un langage qui reflète cela pour être plus intuitif.

Il s'avère que le style fonctionnel se prête à l'utilisation sûre de plusieurs processeurs (car il minimise la mutabilité et les effets secondaires) - quelque chose que nous verrons plus à l'avenir. De plus, la plupart des langages fonctionnels modernes ont des collections avec des itérateurs auxquels vous pouvez transmettre des fonctions. Ces méthodes peuvent répartir leur charge de travail sur plusieurs processeurs de manière très efficace sans même que vous le sachiez.


Je pense que c'est la meilleure réponse - la seule qui fait clairement la distinction entre le processus et les déclarations.
Milind R
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.