以下Haskell代码没有终止,有人可以解释一下原因吗?谢谢.
f = let x = 10 in let x = x * x in x
Run Code Online (Sandbox Code Playgroud)
我认为解释器首先绑定x:10,然后将x*x计算为100并绑定x:100,环境变为x:100,然后整个表达式求值为100
但是,此代码不会终止.
在评估表单的let语句时let foo = bar in baz,foo已经bar在评估时绑定bar- 这是定义是递归的,如果存在具有相同名称的外部绑定,则它将被忽略,因为它不再在范围内.
在评论中,您询问为什么不这样做会收到有关查找x失败的错误.原因是查找x不会失败.Haskell知道它x等于x * x,所以这就是查找产生的.
因此,在x评估时,它将被其定义替换x * x.为了评估它,然后x用它的定义替换第一个s,产生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.