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

infinite loop in Haskell when binding variables

以下 Haskell 代码没有终止,有人可以解释为什么吗?谢谢

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

我认为解释器首先绑定 x : 10, 然后将 x * x 计算为 100 并绑定 x : 100, 环境变为 x : 100, 那么整个表达式的计算结果为 100

但是,此代码不会终止。

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

在评论中,您询问了为什么您没有收到有关 x 查找失败的错误消息。原因是 x 的查找不会失败。 Haskell 知道 x 等于 x * x,所以这就是查找结果。

所以当 x 被评估时,它被替换为它的定义 x * x。为了评估它然后用它的定义替换第一个 xs,产生 x * x * x,然后 x * x * x * x 等等 ad infinitum.

您可能想知道为什么允许值以这种方式递归,所以这里有一个实际有用的示例,不仅会导致无限循环: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.

的先前定义