绑定变量时Haskell中的无限循环

时间:2015-02-17 02:08:34

标签: haskell

以下Haskell代码没有终止,有人可以解释一下原因吗?感谢。

f = let x = 10 in let x = x * x in x

我认为翻译首先绑定x:10, 然后将x * x计算为100并绑定x:100, 环境变成x:100, 然后整个表达式评估为100

但是,此代码不会终止。

1 个答案:

答案 0 :(得分:6)

在评估let foo = bar in baz形式的let语句时,foo在评估bar时已绑定到bar - 这是定义是递归的,如果有的话外部绑定具有相同的名称,它只是被忽略,因为它不再在范围内。

在评论中,您询问为什么不这样做,然后收到有关查找x失败的错误。原因是x的查找不会失败。 Haskell知道x等于x * x,这就是查找产生的内容。

因此,在评估x时,会将其替换为其定义x * x。要评估它,然后用其定义替换x中的第一个,产生x * x * x,然后x * x * x * x等等,无限制地使用。

您可能想知道为什么允许值以这种方式递归,所以这里的示例实际上很有用,并且不会导致无限循环:let xs = 42 : xs in take 2 xs生成结果[42, 42]。此处xs已扩展为42 : xs,然后42 : 42 : xs,然后停止,因为take 2只需要前两个元素,因此它就会停止。

当然,当rhs是一个函数时,很明显,定义是递归的很有用:let fac = \n -> if n = 0 then 1 else n * fac (n-1) - 在这里你显然希望fac引用自身而不是之前的定义fac