Warum wird das Schlüsselwort rec in F # benötigt?

28

In F # muss das recSchlüsselwort verwendet werden. In Haskell muss nicht explizit angegeben werden, ob eine bestimmte Funktion rekursiv ist oder nicht.

Angesichts der Rolle der Rekursion in der funktionalen Programmierung erscheint mir das F # -Design eher seltsam. Handelt es sich um eine gute Entscheidung für das Sprachdesign oder gibt es sie nur aus historischen Gründen oder aufgrund einer Implementierungsbeschränkung?

Simon Bergot
quelle

Antworten:

16

Es gibt einen inhärenten Unterschied in der Haskell- und F # -Semantik. In Haskell führt ein Funktionsaufruf keine echte Berechnung durch, sondern weist ein Heap-Objekt zu, das als "Thunk" bezeichnet wird. Es ist vollkommen in Ordnung, wenn ein Thunk eine Verbindung zu sich selbst oder zu einem anderen Thunk hat. In F # ist ein Funktionsaufruf jedoch ein tatsächlicher Aufruf, der Ausdrücke wie let x = 1 : 2 : x in xungültig macht, da sie erstellt werden müssen x, bevor sie erstellt werden 1 : 2 : x. Es ist jedoch immer noch eine mehr oder weniger vernünftige Definition für eine unendliche Liste. Hier liegen Wurzeln für rec. Wenn Sie mehr wollen, suchen und lesen Sie nach der operativen Semantik für SML und Haskell - das ist anders.

permeakra
quelle
2
AFAIK, Haskell hat absichtlich keine operative Semantik.
Dan_waterworth
@dan_waterworth es ist unmöglich zu kompilieren ohne die definierte operationale Semantik.
Permeakra
8
Die Sprache Haskell definiert keine operative Semantik, sondern stellt eine denotationale Semantik bereit. Wenn Sie einen Compiler erstellen, wird implizit eine operative Semantik definiert. Dies bedeutet jedoch nicht, dass sie Teil des Haskell-Sprachstandards ist.
Dan_waterworth
6
@dan_waterworth In der Praxis gibt es nur eine Implementierung und einen Standard der Haskell-Sprache: ghc, und es gibt auch nur einen F # -Standard: die Implementierung von Microsoft. Theoretisch magst du Recht haben, aber die Praxis ist ein ganz anderes Tier.
Permeakra
19

Diese Frage wurde auf SO beantwortet und enthält einen starken historischen Hintergrund für die Verwendung von "rec".

Hier ist das wichtige Zitat für die Nachwelt:

Funktionen sind in der französischen CAML-Sprachfamilie (einschließlich OCaml) standardmäßig nicht rekursiv. Diese Auswahl erleichtert das Ersetzen von Funktionsdefinitionen (und Variablendefinitionen) mithilfe von let in diesen Sprachen, da Sie auf die vorherige Definition im Hauptteil einer neuen Definition verweisen können. F # hat diese Syntax von OCaml geerbt.

Chris Pitman
quelle
12

Ein Rekursiv letdefiniert eine wesentlich kompliziertere Semantik als eine normale. Aus Gründen der Einfachheit und des übersichtlichen Sprachdesigns gibt es daher einen guten Grund, beides, genauso wie getrennt let, let*und letrecim Schema zu haben.

Einfach let x = y in zist gleichbedeutend mit ((fun x -> z) y). Ein rekursiver Let ist viel komplizierter und kann die Verwendung eines Festkomma-Kombinators beinhalten.

SK-Logik
quelle