Comme en Java, l'une des interfaces les plus utiles permet de préciser que des valeurs sont comparables (sauf que précisement Comparable n'est pas une interface, une bizarrerie de Java). En Java on compare des objets, en OCaml on compare en général des valeurs du même type. On peut donc définir une interface pour les types comparables :
Pour avoir un type comparable, il faut un type, appelé t, et une fonction de comparaision appelé compare. La comparaison suit les conventions habituelles, la valeur retournée doit être un entier, en cohérence à ce que produirait une soustraction entre les deux arguments : si le premier argument est le plus grand le résultat doit être positif, s'il est plus petit le résultat doit être négatif, et le résultat est nul si les éléments sont incomparables.
Dans la librairie standard, cet interface est définie sous le nom Set.OrderedType. Le module String contient une définition de t et de compare compatibles :
On peut donc écrire :
ce qui a pour effet de définir un nouveau module dont la signature est exactement celle donnée par Set.OrderedType (en particulier, le type OrderedString.t est alors abstrait).
Il n'y a par contre pas de module contenant un type appelé t synomyme d'entier, et une fonction comparecorrespondante, mais il est possible de le créer :
Les module Int et String implémentent tous deux l'interface Set.OrderedType.
De même, la librairie standard fournit l'interface des types hachables, disposant d'une fonction de hachage :
Nous voyons que le type doit être fourni avec une fonction de hachage hash et un test d'égalité.
La librairie standard définit quelques interfaces supplémentaires, comme celle des dictionnaires Map.S.
C'est une interface plutôt longue contenant de nombreuses fonctions. En voici un extrait :
La longueur de cette interface suggère qu'il n'est pas ici question de spécifier ce que doit implémenter un module dans le but de pouvoir l'utiliser dans un contexte précis. Dans un tel cas de figure, on aimerait plutôt préciser un nombre minimum d'opérations nécessaire. De fait, cette interface est l'interface d'un module qui peut être généré dans un certain contexte que nous verrons bientôt.
Une autre chose à noter est la présence d'une fonction compare dans Map.S. Cela veut-il dire que Map.S contient Set.OrderedType ? En fait non, car dans Set.OrderedType, le type t n'est pas paramétré. Les deux interfaces sont donc incompatibles; les deux types nommés t ne peuvent pas être les mêmes car ils n'ont pas le même nombre de paramètres.
À toute structure algébrique on peut associer une interface. À titre d'exemple, et comme ils sont particulièrement utiles au programmeur, voici l'interface d'un monoïde :
Il ne faut pas oublier qu'en mathématiques, les structures algébriques sont surtout définies par des lois : par exemple l'addition (qu'on a appelé append ici) est associative dans un monoïde, ou le zéro est neutre pour l'addition. Il n'est pas possible en OCaml de préciser ou de forcer le respect de ces lois, c'est au programmeur de s'assurer du respect des lois.
Des exemples de monoïdes sont : les entiers avec l'addition, les listes ou les chaînes de caractères avec la concaténation, des fonctions d'un ensemble dans lui-même avec la composition.
Nous avons vu de nombreux types paramétrés, et la plupart avait une fonction map, qui avait systématiquement le même type. Cela nous invite à définir l'interface suivante :
De même, nous avons souvent croisé des fonctions bind (ou sous la forme d'opérateur (>>=)). L'interface correspondante est :
Les foncteurs et les monades ont aussi des lois :
Une autre interface usuelle correspond aux itérables de Java. Sur une collection de données nous voulons pouvoir réaliser un calcul dépendant de toutes les valeurs dans la collection. Une interface possible est de demander une fonction fold pour la collection.
Il existe encore plusieurs autres interfaces classiques, mais notre objectif n'est pas d'être exhaustif, ni même d'apprendre à utiliser toutes ces interfaces dans ce cours. Les librairies d'OCaml n'insistent pas particulièrement sur ces interfaces : beaucoup de librairies implémentent plusieurs de ces interfaces sans spécifiquement y faire référence. Par contre, être capable de reconnaître et utiliser correctement ces interfaces permet de comprendre et utiliser correctement de nouvelles librairies utilisant les mêmes abstractions.
Dans le langage Haskell, ces interfaces sont bien plus importantes car elles sont utilisées explicitement à travers un système de classes propre à ce langage. Une quantité très importante de fonctions en Haskell dérivent des principales interfaces du langage et sont donc communes à la plupart des librairies.