作者:大师傅放放风_769 | 来源:互联网 | 2023-05-21 17:35
以下Haskell代码没有终止,有人可以解释一下原因吗?谢谢.
f = let x = 10 in let x = x * x in x
我认为解释器首先绑定x:10,然后将x*x计算为100并绑定x:100,环境变为x:100,然后整个表达式求值为100
但是,此代码不会终止.
1> sepp2k..:
在评估表单的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
.