OCaml est un langage multi-paradigmes : tu disposes de constructions impératives (boucles, références) en plus de tes constructions fonctionnelles (les fonctions sont des valeurs manipulables comme les autres (1)). Ajoute à ça un typage statique fort qui possède de charmantes propriétés (comme la reconstructibilité : de toute expression tu peux déduire le type, tu n'es pas obligé de l'annoter - pas de déclarations chiantes comme en C ou autres). OCaml comporte également une couche objet qui pourrait être intéressante si les gens avaient l'habitude de l'utiliser (mais j'ai pas le sentiment que ça soit dans les mœurs).
Haskell, lui, est « purement » fonctionnel : il ne dispose pas de constructions impératives. Il est également « paresseux » : les expressions ne sont calculées que quand c'est nécessaire. C'est le contraire des langages dits « stricts » (comme OCaml, mais aussi C, Java, Python... quasiment tout le monde en fait). Ça n'est pas à proprement parler une optimisation, parce que même si dans l'idéal ça évite de faire des calculs inutiles, en pratique ça demande davantage de tests, et ça peut rendre imprévisible le comportement du programme (notamment sa consommation mémoire). C'est une façon différente de programmer : ça t'autorise à flirter agréablement avec l'infini, en n'évaluant que ce qui est nécessaire.
Haskell dispose également de ce qu'on appelle des « typeclasses » : ils permettent une surcharge intelligente des opérateurs et des fonctions sur plusieurs types. OCaml n'en dispose pas, et ne peut par exemple pas utiliser le même opérateur d'addition pour les entiers et les flottants : l'opérateur (+) a le type int -> int -> int et l'opérateur (+.) a le type float -> float -> float. Ça a l'air chiant, en pratique ça passe dans ce cas précis. Dans d'autres cas ça peut être un peu irritant. Haskell lui est plus évolué : l'unique opérateur (+) a pour type (Num a) => a -> a -> a . Le a est à lire comme un paramètre de type : ainsi, ce type veut dire « si A est une instance de la classe Num, alors si b et c sont des valeurs de type A, b + c est de type A ». Note bien que ce sont des *types* qui sont des instances de *classes*, pas des valeurs.
D'autre part, certains problèmes sont naturellement impératifs : communiquer avec l'extérieur par exemple. Ceci se fait sans problème en séquençant des instructions Caml - par contre pour Haskell c'est plus difficile. Depuis un bon bout de temps maintenant, la seule façon conseillée de faire des entrées sorties dans ce langage est d'utiliser une construction élaborée appelée « monades ». C'est un mot qui fait peur aux débutants alors qu'il n'est pas très compliqué, mais ça ne s'explique pas en un paragraphe non plus. Les monades sont un concept provenant d'une branche très élaborée des mathématiques, appelée « théorie des catégories ». En gros, elles servent à séquencer des calculs - mais pas nécessairement de façon déterministe, c'est un concept plus général. Elles ne servent pas non plus uniquement à faire des entrées-sorties ou à simuler la programmation impérative. Et surtout, elles ne sont pas réservées à Haskell, il y a de nombreux langages modernes qui peuvent disposer de monades (OCaml ou C# par exemple).
Voilà.
(1) : au cas où tu ne connaîtrais vraiment pas les langages fonctionnels : si tu as déjà utilisé des langages impératifs, tu as certainement déjà manipulé des fonctions via des constructions comme les pointeurs de fonctions ou autres, et tu pourrais te dire donc que n'importe quel langage peut faire ça. En réalité, dans la famille des « fonctionnels » on regroupe les langages qui permettent de manipuler, et notamment de construire, des valeurs fonctionnelles. Par exemple, tu peux facilement définir un opérateur de composition de fonctions en Caml ou en Haskell. En C avec des pointeurs de fonctions, je ne vois pas vraiment comment faire.
[^] # Re: typage mou
Posté par ZankFrappa . En réponse à la dépêche Quelques nouvelles de Go, le langage de programmation. Évalué à 10.
Haskell, lui, est « purement » fonctionnel : il ne dispose pas de constructions impératives. Il est également « paresseux » : les expressions ne sont calculées que quand c'est nécessaire. C'est le contraire des langages dits « stricts » (comme OCaml, mais aussi C, Java, Python... quasiment tout le monde en fait). Ça n'est pas à proprement parler une optimisation, parce que même si dans l'idéal ça évite de faire des calculs inutiles, en pratique ça demande davantage de tests, et ça peut rendre imprévisible le comportement du programme (notamment sa consommation mémoire). C'est une façon différente de programmer : ça t'autorise à flirter agréablement avec l'infini, en n'évaluant que ce qui est nécessaire.
Haskell dispose également de ce qu'on appelle des « typeclasses » : ils permettent une surcharge intelligente des opérateurs et des fonctions sur plusieurs types. OCaml n'en dispose pas, et ne peut par exemple pas utiliser le même opérateur d'addition pour les entiers et les flottants : l'opérateur (+) a le type int -> int -> int et l'opérateur (+.) a le type float -> float -> float. Ça a l'air chiant, en pratique ça passe dans ce cas précis. Dans d'autres cas ça peut être un peu irritant. Haskell lui est plus évolué : l'unique opérateur (+) a pour type (Num a) => a -> a -> a . Le a est à lire comme un paramètre de type : ainsi, ce type veut dire « si A est une instance de la classe Num, alors si b et c sont des valeurs de type A, b + c est de type A ». Note bien que ce sont des *types* qui sont des instances de *classes*, pas des valeurs.
D'autre part, certains problèmes sont naturellement impératifs : communiquer avec l'extérieur par exemple. Ceci se fait sans problème en séquençant des instructions Caml - par contre pour Haskell c'est plus difficile. Depuis un bon bout de temps maintenant, la seule façon conseillée de faire des entrées sorties dans ce langage est d'utiliser une construction élaborée appelée « monades ». C'est un mot qui fait peur aux débutants alors qu'il n'est pas très compliqué, mais ça ne s'explique pas en un paragraphe non plus. Les monades sont un concept provenant d'une branche très élaborée des mathématiques, appelée « théorie des catégories ». En gros, elles servent à séquencer des calculs - mais pas nécessairement de façon déterministe, c'est un concept plus général. Elles ne servent pas non plus uniquement à faire des entrées-sorties ou à simuler la programmation impérative. Et surtout, elles ne sont pas réservées à Haskell, il y a de nombreux langages modernes qui peuvent disposer de monades (OCaml ou C# par exemple).
Voilà.
(1) : au cas où tu ne connaîtrais vraiment pas les langages fonctionnels : si tu as déjà utilisé des langages impératifs, tu as certainement déjà manipulé des fonctions via des constructions comme les pointeurs de fonctions ou autres, et tu pourrais te dire donc que n'importe quel langage peut faire ça. En réalité, dans la famille des « fonctionnels » on regroupe les langages qui permettent de manipuler, et notamment de construire, des valeurs fonctionnelles. Par exemple, tu peux facilement définir un opérateur de composition de fonctions en Caml ou en Haskell. En C avec des pointeurs de fonctions, je ne vois pas vraiment comment faire.