haskell - 绑定(bind)变量时Haskell中的无限循环

标签 haskell

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

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

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

但是,此代码不会终止。

最佳答案

当评估 let foo = bar in baz 形式的 let 语句时,foo 在评估 时已经绑定(bind)到 bar >bar - 即定义是递归的,如果有同名的外部绑定(bind),它会被忽略,因为它不再在范围内。

在评论中,您询问了为什么您没有收到关于 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 定义。

关于haskell - 绑定(bind)变量时Haskell中的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28553559/

相关文章:

haskell - 如何编写 attoparsec 的 takeWhile1 的更通用(但高效)版本?

haskell - 使用darcs 将单个文件恢复到以前的版本

haskell - 需要帮助理解 Haskell 的惰性求值行为

haskell - 在 Haskell Web 应用程序中管理加密随机数生成器

Haskell 从 IO 中提取长度(回复 [Data.ByteString.Internal.ByteString])

haskell - 在列表中使用带有尾部尾部的 cons 会引发错误

function - Haskell 映射和过滤器

user-interface - 当用户停止输入文本时运行函数

haskell - Haskell 中的新类型行为

scala - 命令式类型与普通的旧子类型