绑定变量时 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
。为了评估它然后用它的定义替换第一个 x
s,产生 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
.
的先前定义
以下 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
。为了评估它然后用它的定义替换第一个 x
s,产生 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
.