Une raison cruciale de l'utilisation explicite de rec
est liée à l'inférence de type Hindley-Milner, qui sous-tend tous les langages de programmation fonctionnelle typés statiquement (bien que modifiés et étendus de diverses manières).
Si vous avez une définition let f x = x
, vous vous attendez à ce qu'elle ait un type 'a -> 'a
et qu'elle soit applicable sur différents 'a
types à différents points. Mais également, si vous écrivez let g x = (x + 1) + ...
, vous vous attendez x
à être traité comme un int
dans le reste du corps de g
.
La manière dont l'inférence Hindley-Milner traite cette distinction passe par une étape de généralisation explicite . À certains moments lors du traitement de votre programme, le système de types s'arrête et dit "ok, les types de ces définitions seront généralisés à ce stade, de sorte que lorsque quelqu'un les utilise, toutes les variables de type libre dans leur type seront fraîchement instanciées, et donc n'interférera avec aucune autre utilisation de cette définition. "
Il s'avère que le bon endroit pour faire cette généralisation est après avoir vérifié un ensemble de fonctions mutuellement récursives. Tout plus tôt, et vous généraliserez trop, conduisant à des situations où les types pourraient réellement entrer en collision. Plus tard, et vous généraliserez trop peu, créant des définitions qui ne peuvent pas être utilisées avec plusieurs instanciations de types.
Donc, étant donné que le vérificateur de type a besoin de savoir quels ensembles de définitions sont mutuellement récursifs, que peut-il faire? Une possibilité consiste simplement à effectuer une analyse de dépendance sur toutes les définitions d'une étendue et à les réorganiser dans les plus petits groupes possibles. Haskell le fait en fait, mais dans des langages comme F # (et OCaml et SML) qui ont des effets secondaires illimités, c'est une mauvaise idée car cela pourrait également réorganiser les effets secondaires. Donc, à la place, il demande à l'utilisateur de marquer explicitement quelles définitions sont mutuellement récursives, et donc par extension où la généralisation doit avoir lieu.