web-dev-qa-db-fra.com

Que signifie «pur» dans «langage fonctionnel pur»?

Haskell a été appelé un "langage fonctionnel pur".

Que signifie "pur" dans ce contexte? Quelles conséquences cela a-t-il pour un programmeur?

56
Bobby S

Dans un langage fonctionnel pur, vous ne pouvez rien faire qui ait un effet secondaire.

Un effet secondaire signifierait que l'évaluation d'une expression change un état interne qui entraînerait plus tard l'évaluation de la même expression pour un résultat différent. Dans un langage fonctionnel pur, vous pouvez évaluer la même expression aussi souvent que vous le souhaitez avec les mêmes arguments, et elle renverrait toujours la même valeur, car il n'y a pas d'état à modifier.

Par exemple, un langage fonctionnel pur ne peut pas avoir d'opérateur d'affectation ni faire d'entrée/sortie, bien qu'à des fins pratiques, même les langages fonctionnels purs appellent souvent des bibliothèques impures pour effectuer des E/S.

59
Joel Spolsky

"Pur" et "fonctionnel" sont deux concepts distincts, bien que l'un ne soit pas très utile sans l'autre.

Une expression pure est idempotente: elle peut être évaluée n'importe quel nombre de fois, avec des résultats identiques à chaque fois. Cela signifie que l'expression ne peut avoir aucun effet secondaire observable. Par exemple, si une fonction mute ses arguments, définit une variable quelque part ou change de comportement en fonction de quelque chose d'autre que son entrée seule, cet appel de fonction n'est pas pur.

Un langage de programmation fonctionnel est un langage dans lequel les fonctions sont de première classe. En d'autres termes, vous pouvez manipuler des fonctions avec exactement la même facilité avec laquelle vous pouvez manipuler toutes les autres valeurs de première classe. Par exemple, être capable d'utiliser une "fonction renvoyant un booléen" comme une "structure de données représentant un ensemble" serait facile dans un langage de programmation fonctionnel.

La programmation dans les langages de programmation fonctionnels est souvent effectuée dans un style principalement pur, et il est difficile d'être strictement pur sans manipulation de fonction d'ordre supérieur activée par les langages de programmation fonctionnels.

Haskell est un langage de programmation fonctionnel, dans lequel (presque) toutes les expressions sont pures; ainsi, Haskell est un langage de programmation purement fonctionnel.

32
ephemient

Une fonction pure est une fonction qui n'a pas d'effets secondaires - elle prend une valeur et donne une valeur. Il n'y a aucun état global qui modifie les fonctions. Un langage fonctionnel pur est un langage qui force les fonctions à être pures. La pureté a un certain nombre de conséquences intéressantes, telles que le fait que l'évaluation peut être paresseuse - puisqu'un appel de fonction n'a d'autre but que de renvoyer une valeur, alors vous n'avez pas besoin d'exécuter réellement la fonction si vous n'utilisez pas Sa valeur. Grâce à cela, des choses comme les fonctions récursives sur des listes infinies sont courantes dans Haskell.

Une autre conséquence est que peu importe l'ordre dans lequel les fonctions sont évaluées - puisqu'elles ne peuvent pas s'influencer mutuellement, vous pouvez les faire dans n'importe quel ordre qui vous convient. Cela signifie que certains des problèmes posés par la programmation parallèle n'existent tout simplement pas, car il n'y a pas de "mauvais" ou de "bon" ordre d'exécution des fonctions.

24
Chuck

À strictement parler, un langage fonctionnel pur est un langage fonctionnel (c'est-à-dire un langage où les fonctions sont des valeurs de première classe) où les expressions n'ont pas d'effets secondaires. Le terme "langage purement fonctionnel" est synonyme.

Selon cette définition, Haskell n'est pas un pur langage fonctionnel. Toute langue dans laquelle vous pouvez écrire des programmes qui affichent leurs résultats, lire et écrire des fichiers, avoir une interface graphique, etc., n'est pas purement fonctionnelle. Par conséquent, aucun langage de programmation à usage général n'est purement fonctionnel (mais il existe des langages purement fonctionnels spécifiques à un domaine: ils peuvent généralement être considérés comme des langages intégrés d'une certaine manière).

Il existe un sens détendu utile dans lequel des langues comme Haskell et Erlang peuvent être considérées comme purement fonctionnelles, mais pas des langues comme ML et Scheme. Un langage peut être considéré comme purement fonctionnel s'il existe un sous-ensemble raisonnablement grand, utile et bien caractérisé où les effets secondaires sont impossibles. Par exemple, dans Haskell, tous les programmes dont le type n'est pas construit à partir de IO ou d'une autre monade dénotant les effets sont sans effets secondaires. Dans Erlang, tous les programmes qui n'utilisent pas de bibliothèques induisant des entrées-sorties ou des fonctionnalités de concurrence sont sans effet secondaire (c'est plus un étirement que le cas Haskell). Inversement, dans ML ou Scheme, un effet secondaire peut être enterré dans n'importe quelle fonction.

Dans cette perspective, le sous-ensemble purement fonctionnel de Haskell peut être considéré comme le langage intégré pour gérer le comportement à l'intérieur de chaque monade (bien sûr, c'est une perspective étrange, car presque tout le calcul se produit dans ce sous-ensemble "intégré"), et le sous-ensemble purement fonctionnel d'Erlang peut être vu comme le langage embarqué traite du comportement local.


Graham Hutton a une perspective légèrement différente et assez intéressante sur le sujet langages purement fonctionnels :

Parfois, le terme "purement fonctionnel" est également utilisé dans un sens plus large pour désigner les langages qui pourraient incorporer des effets de calcul, mais sans altérer la notion de "fonction" (comme en témoigne le fait que les propriétés essentielles des fonctions sont préservées.) , l'évaluation d'une expression peut produire une "tâche", qui est ensuite exécutée séparément pour provoquer des effets de calcul. Les phases d'évaluation et d'exécution sont séparées de telle sorte que la phase d'évaluation ne compromet pas les propriétés standard des expressions et des fonctions. Les mécanismes d'entrée/sortie de Haskell, par exemple, sont de ce type.

C'est à dire. dans Haskell, une fonction a le type a -> b et ne peut pas avoir d'effets secondaires. Une expression de type IO (a -> b) peut avoir des effets secondaires, mais ce n'est pas une fonction. Ainsi, dans Haskell, les fonctions doivent être pures, Haskell est donc purement fonctionnel.

11
Gilles

Comme il ne peut pas y avoir d'effets secondaires dans le code fonctionnel pur, les tests deviennent beaucoup plus faciles car il n'y a aucun état externe à vérifier ou à vérifier. De plus, à cause de cela, l'extension du code peut devenir plus facile.

J'ai perdu le compte du nombre de fois où j'ai eu des problèmes avec des effets secondaires non évidents lors de l'extension/correction (ou tentative de correction) du code.

4
Marcus Borkenhagen

Comme d'autres l'ont mentionné, le terme "pur" dans "langage de programmation fonctionnel pur" fait référence au manque d'effets secondaires observables. Pour moi, cela mène directement à la question:

Qu'est-ce qu'un effet secondaire?

J'ai vu des effets secondaires expliqués à la fois comme

  • quelque chose qu'une fonction fait autre que simplement calculer son résultat
  • quelque chose qui peut affecter le résultat d'une fonction autre que les entrées de la fonction.

Si la première définition est la bonne, alors toute fonction qui fait des E/S (par exemple, écrire dans un fichier) ne peut pas être considérée comme une fonction "pure". Alors que les programmes Haskell peuvent appeler des fonctions qui provoquent l'exécution d'E/S, il semblerait que Haskell ne soit pas un langage de programmation purement fonctionnel (comme on le prétend) selon cette définition.

Pour cela et pour d'autres raisons, je pense que la deuxième définition est la plus utile. Selon la deuxième définition, Haskell peut toujours prétendre être un langage de programmation fonctionnelle complètement pur, car les fonctions qui entraînent l'exécution d'E/S calculent les résultats en fonction uniquement des entrées de fonction. La façon dont Haskell concilie ces exigences apparemment contradictoires est assez intéressante, je pense, mais je résisterai à la tentation de m'éloigner davantage de la réponse à la vraie question.

4
Daniel Pratt

Amr Sabry a écrit un papier sur ce qu'est un langage fonctionnel pur. Haskell est par cette définition considéré comme pur, si nous ignorons des choses comme unsafePerformIO. L'utilisation de cette définition rend également ML et Erlang impurs. Il existe des sous-ensembles de la plupart des langages qui peuvent être considérés comme purs, mais personnellement, je ne pense pas qu'il soit très utile de parler de C comme étant un langage pur.

Un ordre supérieur est orthogonal à la pureté, vous pouvez concevoir un langage fonctionnel de premier ordre pur.

2
Anon'