为什么在F#中需要rec关键字?


28

在F#中,必须使用rec关键字。在Haskell中,无需显式判断给定函数是否是递归的。

考虑到递归在函数式编程中的作用,F#设计对我来说似乎很奇怪。这是一个好的语言设计决策,还是仅出于历史原因或由于实施限制而存在?

Answers:


16

Haskell和F#语义存在固有的差异。在Haskell中,函数调用不执行任何实际计算,而是分配一个称为“ thunk”的堆对象。一个怪人与自己或另一个怪人建立链接是完全可以的。但是,在F#中,函数调用是实际调用,使诸如let x = 1 : 2 : x in x无效之类的表达式成为必需,因为它需要x在构造之前1 : 2 : x构造。但是,它对于无限列表仍然或多或少是合理的,应该有一些定义它的方法。这是扎根的根源rec。如果您想要更多,请搜索并阅读SML和Haskell的操作语义-这是不同的。


2
AFAIK,Haskell故意没有操作语义。
dan_waterworth 2012年

@dan_waterworth,如果没有定义操作语义,就不可能进行编译。
permeakra 2012年

8
Haskell语言没有定义操作语义,而是提供了指称语义。构造编译器时,将隐式定义操作语义,但这并不意味着它是Haskell语言标准的一部分。
dan_waterworth 2012年

6
@dan_waterworth实际上,Haskell语言只有一种实现和标准:ghc,只有一种F#标准:Microsoft的实现。因此从理论上讲您可能是正确的,但实践却完全不同。
permeakra 2012年

19

这个问题已经在SO上得到了回答,它包括了为什么使用“ rec”的强大历史背景。

这是后代的重要报价:

默认情况下,法语CAML语言家族(包括OCaml)中的函数不是递归的。通过这种选择,可以轻松地在这些语言中使用let取代函数(和变量)定义,因为您可以在新定义体内引用以前的定义。F#从OCaml继承了此语法。


12

递归let定义的语义要比普通语义复杂得多。因此,为了简单和干净的语言设计的缘故,有一个很好的理由兼得,也一样具有独立的letlet*letrec方案。

简单let x = y in z等同于((fun x -> z) y)。递归let更为复杂,可能涉及使用定点组合器。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.