Ein entscheidender Grund für die explizite Verwendung von rec
ist die Hindley-Milner-Typinferenz, die allen statisch typisierten funktionalen Programmiersprachen zugrunde liegt (wenn auch auf verschiedene Weise geändert und erweitert).
Wenn Sie eine Definition haben let f x = x
, erwarten Sie, dass sie einen Typ hat 'a -> 'a
und 'a
an verschiedenen Stellen auf verschiedene Typen anwendbar ist . Aber ebenso, wenn Sie schreiben let g x = (x + 1) + ...
, würden Sie erwarten x
, als int
im Rest des Körpers von behandelt zu werdeng
.
Die Art und Weise, wie die Hindley-Milner-Folgerung mit dieser Unterscheidung umgeht, erfolgt durch einen expliziten Verallgemeinerungsschritt . An bestimmten Stellen bei der Verarbeitung Ihres Programms stoppt das Typsystem und sagt "OK, die Typen dieser Definitionen werden an dieser Stelle verallgemeinert, sodass alle freien Typvariablen in ihrem Typ frisch sind , wenn jemand sie verwendet instanziiert werden und somit wird keine anderen Verwendungen dieser Definition stören. "
Es stellt sich heraus, dass der sinnvolle Ort für diese Verallgemeinerung die Überprüfung eines gegenseitig rekursiven Satzes von Funktionen ist. Früher, und Sie verallgemeinern zu viel, was zu Situationen führt, in denen Typen tatsächlich kollidieren könnten. Später, und Sie werden zu wenig verallgemeinern und Definitionen erstellen, die nicht mit Instanzen von mehreren Typen verwendet werden können.
Was kann der Typprüfer tun, wenn er wissen muss, welche Definitionssätze sich gegenseitig rekursiv sind? Eine Möglichkeit besteht darin, einfach eine Abhängigkeitsanalyse für alle Definitionen in einem Bereich durchzuführen und sie in die kleinstmöglichen Gruppen zu ordnen. Haskell tut dies tatsächlich, aber in Sprachen wie F # (und OCaml und SML), die uneingeschränkte Nebenwirkungen haben, ist dies eine schlechte Idee, da möglicherweise auch die Nebenwirkungen neu angeordnet werden. Stattdessen wird der Benutzer aufgefordert, explizit zu markieren, welche Definitionen sich gegenseitig rekursiv sind, und somit durch Erweiterung, wo eine Verallgemeinerung erfolgen soll.