C’est peut-être une question philosophique, mais je pense qu’il ya une réponse objective à cette question.
Si vous lisez l'article de Wikipédia sur Haskell, vous trouverez ce qui suit:
La langue est enracinée dans les observations de Haskell Curry et de ses descendants intellectuels, selon lesquelles "une preuve est un programme; la formule prouvée est un type pour le programme"
Maintenant, ce que je demande, c'est: cela ne s'applique-t-il pas à peu près à tous les langages de programmation? Quelle fonctionnalité (ou ensemble de fonctionnalités) de Haskell le rend conforme à cette déclaration? En d’autres termes, quels sont les effets remarquables de cette affirmation sur la conception de la langue?
Réponses:
Le concept essentiel s’applique universellement d’une certaine manière, oui, mais rarement de manière utile.
Pour commencer, du point de vue de la théorie des types, les langages "dynamiques" sont considérés comme ayant un seul type, qui contient (entre autres) des métadonnées sur la nature de la valeur vue par le programmeur, y compris ce que ces langages dynamiques appellent un "type" eux-mêmes (ce qui n'est pas la même chose, conceptuellement). De telles preuves étant susceptibles de ne pas être intéressantes, ce concept concerne principalement les langages utilisant des systèmes de types statiques.
En outre, de nombreuses langues supposées avoir un "système de types statiques" doivent être considérées comme dynamiques dans la pratique, dans ce contexte, car elles permettent l'inspection et la conversion de types au moment de l'exécution. En particulier, cela signifie toute langue avec un support intégré par défaut pour la "réflexion" ou autre. C #, par exemple.
Haskell présente une quantité inhabituelle d'informations attendues par un type. En particulier, les fonctions ne peuvent dépendre d'aucune valeur autre que celles spécifiées comme arguments. En revanche, dans une langue avec des variables globales modifiables, toute fonction peut (potentiellement) inspecter ces valeurs et modifier le comportement en conséquence. Ainsi, une fonction de Haskell avec type
A -> B
peut être considérée comme un programme miniature prouvant que celaA
impliqueB
; une fonction équivalente dans de nombreuses autres langues ne ferait que nous dire queA
, quel que soit l'état global combiné, cela impliqueB
.Notez que bien que Haskell prenne en charge des éléments tels que les types de réflexion et les types dynamiques, l' utilisation de telles fonctionnalités doit être indiquée dans la signature de type d'une fonction; de même pour l'utilisation de l'état global. Ni est disponible par défaut.
Il existe également des moyens de casser des choses dans Haskell, par exemple en autorisant des exceptions d'exécution ou en utilisant des opérations primitives non standard fournies par le compilateur, mais il existe de fortes espérances sur le fait qu'elles ne seront utilisées que si elles sont parfaitement comprises ». t endommager le sens du code externe. En théorie, on pourrait en dire autant des autres langues, mais dans la plupart des autres langues, il est plus difficile de faire des choses sans "tricher" et moins mal vu de "tricher". Et bien sûr, dans les vrais langages "dynamiques", le tout reste sans importance.
Le concept peut également être poussé beaucoup plus loin qu’en Haskell.
la source
Vous avez raison de dire que la correspondance entre Curry et Howard est très générale. Il est intéressant de se familiariser avec son histoire: http://en.wikipedia.org/wiki/Curry-Howard_correspondence
Vous noterez que, telle que formulée à l'origine, cette correspondance s'appliquait particulièrement à la logique intuitionniste d'un côté et au calcul lambda simplement typé (STLC) de l'autre.
Haskell classique - soit les versions de 1998 ou même antérieures, était très proche du STLC et, pour l’essentiel, il existait une traduction très simple et directe entre toute expression donnée en Haskell et un terme correspondant dans le STLC (avec récursion et quelques types primitifs). Cela a donc rendu Curry-Howard très explicite. Aujourd'hui, grâce aux extensions, une telle traduction est un peu plus complexe.
Donc, dans un sens, la question est de savoir pourquoi Haskell "se désargue" dans le STLC de manière aussi simple. Deux choses viennent à l'esprit:
Haskell, comme la plupart des langues, échoue également en ce qui concerne l’application directe de la correspondance Curry-Howard. Haskell, en tant que langage complet, contient la possibilité d'une récursion illimitée, et donc de non-résiliation. Le STLC n'a pas d'opérateur de point fixe, n'est pas complet et se normalise fortement , ce qui signifie qu'aucune réduction d'un terme dans le STLC n'aboutira. La possibilité de récursivité signifie que l'on peut "tricher" Curry-Howard. Par exemple,
let x = x in x
a le typeforall a. a
- c’est-à-dire qu’il ne revient jamais, je peux prétendre que cela me donne quelque chose! Comme nous pouvons toujours le faire en Haskell, cela signifie que nous ne pouvons pas "croire" pleinement en une preuve correspondant à un programme Haskell, à moins de disposer d'une preuve distincte de la fin du programme.La lignée de programmation fonctionnelle antérieure à Haskell (notamment la famille ML) résultait de la recherche en CS centrée sur la construction de langages sur lesquels vous pouviez facilement prouver des choses (entre autres), recherche très consciente et issue de la théorie de l’hébergement. Inversement, Haskell a servi à la fois de langage hôte et d'inspiration à un certain nombre d'assistants de preuve en cours de développement, tels que Agda et Epigram, qui sont enracinés dans des développements de la théorie des types très liés à la lignée de CH.
la source
A -> B
, à partir d'unA
, produira unB
ou rien du tout. Il ne produira jamais de typeC
, et quelle que soit la valeur du typeB
fourni ou dépend toujours exclusivement du typeA
fourni.Void
non? La paresse rend les choses plus compliquées et moins compliquées. Je dirais qu'une fonction de produitA -> B
toujours une valeur de typeB
, mais cette valeur peut avoir moins d'informations que ce à quoi on pourrait s'attendre.Au premier ordre, la plupart des autres langues (faiblement et / ou uni-typées) ne prennent pas en charge la délimitation stricte au niveau de la langue entre un
et la relation stricte entre les deux. Au mieux, les meilleures garanties offertes par d’autres langues sont:
Notez que par type , nous nous référons à une proposition , et donc à quelque chose qui décrit beaucoup plus d’informations que simplement int ou bool . En Haskell, il y a une culture qui pénètre d' une fonction qui n'est affectée que par ses arguments - sans exception *.
Pour être un peu plus rigoureux, l’idée générale est qu’en imposant une approche intuitionniste rigide à (presque) toutes les constructions de programme (c’est-à-dire que nous ne pouvons que prouver ce que nous pouvons construire), et en limitant l’ensemble des constructions primitives dans un tel environnement. façon dont nous avons
Les constructions Haskell ont tendance à très bien se prêter à la réflexion sur leur comportement. Si nous pouvons construire une preuve (lire: fonction) prouvant
A
impliqueB
, c'est a très propriétés utiles:A
, on peut en construire unB
)A
, et rien d' autre.nous permettant ainsi de raisonner efficacement sur les invariants locaux / globaux. Pour revenir à la question initiale. Les fonctionnalités linguistiques de Haskell qui facilitent le mieux cet état d'esprit sont les suivantes:
Aucune d'entre elles n'est unique à Haskell (beaucoup de ces idées sont incroyablement anciennes). Cependant, lorsqu'il est combiné avec un riche ensemble d'abstractions dans les bibliothèques standards (habituellement trouvés dans les classes de type), divers sucrage niveau de syntaxe et d' un strict engagement à la pureté dans la conception du programme, nous nous retrouvons avec une langue qui réussit à être à la fois Pratique pour les applications du monde réel , mais en même temps, il est plus facile de raisonner sur les langues les plus traditionnelles.
Cette question mérite une réponse suffisamment profonde et je ne pourrais pas lui rendre justice dans ce contexte. Je suggérerais d'en lire plus sur wikipedia / dans la littérature:
* NB: Je passe sous silence / ignore certains des aspects les plus délicats des impuretés de Haskell (exceptions, non-résiliation, etc.) qui ne feraient que complexifier l'argument.
la source
Quelle caractéristique? Le système de types (statique, pur, polymorphe). Les "théorèmes gratuits" de Wadler constituent un bon point de départ. Effet notable sur la conception de la langue? Le type IO, les classes de type.
la source
La hiérarchie de Kleene nous montre que les preuves ne sont pas des programmes.
La première relation récursive est soit:
Les premières relations énumérables récursivement sont:
Ainsi, un programme est un théorème et l'itération à laquelle il s'arrête ressemble à la preuve qui prouve le théorème.
Lorsqu'un programme est correctement produit à partir d'une spécification, nous devons être en mesure de prouver qu'il satisfait à la spécification, et si nous pouvons prouver qu'un programme satisfait à une spécification, la synthèse de programme est correcte. Nous effectuons donc la synthèse du programme si et seulement si nous prouvons que le programme satisfait aux spécifications. Le théorème selon lequel le programme satisfait à la spécification est le programme en ce sens qu'il fait référence au programme synthétisé.
Les fausses conclusions de Martin Lof n'ont jamais produit de programme informatique et il est étonnant que les gens croient qu'il s'agit d'une méthodologie de synthèse de programme. Aucun exemple complet d'un programme en cours de synthèse n'a jamais été donné. Une spécification telle que "entrer un type et sortir un programme de ce type" n'est pas une fonction. Il existe plusieurs programmes de ce type et choisir l'un au hasard n'est pas une fonction récursive ni même une fonction. C'est juste une tentative stupide de montrer la synthèse de programme avec un programme stupide qui ne représente pas un vrai programme informatique calculant une fonction récursive.
la source
doesn't this really apply to pretty much all the programming languages?
" Cette réponse prétend / montre que cette hypothèse est invalide, il est donc insensé de traiter le reste des questions basées sur une prémisse erronée. .