Re: [Haskell-fr] Re: inférence

Dupont Corentin corentin.dupont at gmail.com
Thu Sep 20 08:55:28 EDT 2007


Pour ma société, j'ai écrit une petite introduction à Haskell.
Vos critiques sont les bienvenues.
Je vous la fait lire:


Titre : Présentation du langage Haskell

Salut à tous !

Je me suis intéressé (à titre personnel) récemment à un nouveau
langage de programmation généraliste : Haskell.

L'article est à classer dans la catégorie « R&D » :
Malgré tous les concepts intéressants qu'il introduit, il est encore
peu utilisé dans le monde industriel. Mais il vaut le détour !!
Haskell est un langage récent (moins d'une dizaine d'années).

Quelques stats pour vous donner envie de lire la suite :
-	10 fois moins de lignes de code qu'en C
-	Grande expressivité.
-	Compréhension, maintenabilité largement accrue.


C'est un langage basé sur une théorie mathématique (la théorie de
catégories). Ce langage est « fonctionnel pur », par opposition aux
langages « impératifs », dont font parties tous les langages les plus
connus (C, C++, Ada, Java, Pascal…).
Cela induit un mode de programmation radicalement différent !

Haskell est :

-	paresseux
-	pleinement fonctionnel
-	fortement typé, et supporte l'inférence de type


Haskell est effectivement paresseux, mais ce n'est pas péjoratif !
Cela signifie qu'il n'évalue pas une expression si ce n'est pas
nécessaire. Si le résultat d'un calcul n'est pas utilisé dans la suite
du programme, il n'est pas évalué.

Cela induit un gain évident en terme de temps de traitement.
Cela améliore aussi le design des programmes puisque cela décharge le
programmeur de coder certaines optimisations, pour se concentrer sur
le métier de son logiciel.

Mais surtout, cela permet de faire certaines abstractions très
intéressantes : comme par exemple des structures de données de taille
infinie.
En Haskell il est tout à fait possible de déclarer un « tableau » de
taille infinie, par exemple un tableau contenant tous les éléments de
la suite de Fibonacci !
Bien sûr vous choisirez de n'afficher que les n premiers éléments, et
Haskell décidera de ne calculer que ceux là. (Voir l'exemple
faramineux de wikipedia…)


Ensuite Haskell est pleinement fonctionnel : les fonctions sont des
objets de « 1ere classe ».
Cela signifie que les fonctions peuvent être traitées comme des
variables. Donc une fonction peut être passée en paramètre à une autre
fonction, récupérée en paramètre de retour etc.

Haskell supporte les fonctions anonymes et les fonctions « lambda ».
Cela permet par exemple de décrire une fonction (simple) dans la zone
de paramètres d'une autre fonction.
Un bon exemple vaut mieux qu'un long discours :

map (+1) [1..10]

map est une fonction à 2 arguments : une fonction et une liste (ici
[1..10]). Comme on peut s'y attendre, map applique la fonction à tous
les éléments de la liste et retourne une liste résultante.
Mais mais mais ??? « (+1) » c'est une fonction ? Eh bien oui, c'est
une fonction anonyme (je ne l'ai pas déclarée avec un petit nom).

Et la fonction « + » prend bien 2 arguments ? Je n'en voit qu'un (le 1
dans l'exemple)? Il s'agit du mécanisme d' « évaluation partielle » de
Haskell. Si vous avez une fonction de 2 paramètres et que vous
fournissez les 2 paramètres, super.
Mais si vous ne fournissez qu'un paramètre, le résultat de l'opération
sera… Une fonction bien sur ! Une fonction de l'autre paramètre.
Et cette fonction à un paramètre est ce qu'attend la fonction map.
Alors, quel est le résultat de cette ligne de code ? ;)


Haskell supporte la curryfication. Cette opération, du nom de son
inventeur, est à la base d'Haskell. D'ailleurs, devinez le prénom de
ce Mr Curry… Haskell bien sur !!


Il existe bien sùr une algèbre sur les fonctions : l'addition, la composition…
Vous pouvez donc définir une fonction en une ligne par simple
composition de deux autres fonctions à l'aide de l'opérateur rond « °
». Ce qui rend les choses assez lisible : dans un gros programme les
fonctionnalités de haut niveau sont souvent cassés en plusieurs
fonctions plus simple. Une fois définis les fonctions simples, vous
les ressemblez en une ligne avec l'opérateur rond.


Haskell est statiquement et fortement typé. Le système de typage est
très évolué, et vous évitera de nombreuses erreurs de programmation.

Je termine par le plus dur :
Haskell est un langage fonctionnel « pure ».
Cela signifie qu'il n'y a aucuns effets de bords, et donc qu'il ne
supporte pas l'affectation.

Par exemple dans un programme en C, je pourrais avoir l'instruction suivante :

a = f + g

f et g sont des fonction, a un entier.
Dans le cadre d'un refactoring, je pourrais être amené à vouloir écrire :

a = g + f

Eh bien ce n'est à priori pas possible car en C comme dans d'autres
langages, les fonctions ont des effets de bord : f peut modifier le
contexte qui sera utilisé par g.

En Haskell, le retour d'une fonction dépend uniquement de ses
paramètres, de rien d'autre.
Si vous l'appelez à n'importe quel moment avec les mêmes paramètres,
le résultat sera le même.
Cela donne une très grande plasticité et maintenabilité au programme.
Tout devient plus clair !
Mais il faut reconnaître que les programmes sont plus difficiles à écrire.

Cette aspect « pas d'affectation » ouvre la porte à de nombreuses
fonctionnalités impossible sans, dont la paresse.
A noter aussi que comme conséquence, l'ordre des instructions n'a pas
d'importance… Haskell est uniquement déclaratif.

Haskell intègre aussi de nombreuses autres fonctionnalités que je n'ai
malheureusement pas le temps de développer ici, dont :
-	la compréhension de listes
-	le pattern matching pour les paramètres
-	les monades et les classes de types…



Références :
www.haskell.org
http://en.wikipedia.org/wiki/Haskell_(programming_language)

Ouvrages de référence :
Yet Another Haskell Tutorial
A Gentle Introduction to Haskell

Contrairement à ce que son nom indique, ce dernier ouvrage n'est pas
gentil du tout, commencez plutôt par :
Haskell for C Programmers


More information about the Haskell-fr mailing list