Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
绑定变量时Haskell中的无限循环_Haskell - Fatal编程技术网

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

绑定变量时Haskell中的无限循环,haskell,Haskell,下面的Haskell代码没有终止,有人能解释一下原因吗?谢谢 f = let x = 10 in let x = x * x in x 我想口译员先绑定x:10, 然后计算x*x到100并绑定x:100, 环境变成x:100, 然后整个表达式的计算结果为100 但是,此代码不会终止。当计算baz中形式为let foo=bar的let语句时,foo在计算bar时已绑定到bar——即定义是递归的,如果存在同名的外部绑定,它只是被忽略,因为它不再在范围内 在一条评论中,您询问了为什么不查找x失败的原

下面的Haskell代码没有终止,有人能解释一下原因吗?谢谢

f = let x = 10 in let x = x * x in x
我想口译员先绑定x:10, 然后计算x*x到100并绑定x:100, 环境变成x:100, 然后整个表达式的计算结果为100


但是,此代码不会终止。

当计算baz中形式为
let foo=bar的let语句时,
foo
在计算
bar
时已绑定到
bar
——即定义是递归的,如果存在同名的外部绑定,它只是被忽略,因为它不再在范围内

在一条评论中,您询问了为什么不查找
x
失败的原因。原因是查找
x
不会失败。Haskell知道
x
等于
x*x
,所以这就是查找产生的结果

因此,当计算
x
时,它将替换为其定义
x*x
。评估它然后用它的定义替换第一个
x
s,产生
x*x*x
,然后
x*x*x
,依此类推

您可能想知道为什么允许值以这种方式递归,因此这里有一个实际有用的示例,它不仅会导致无限循环:
让xs=42:xs在take 2 xs中生成结果
[42,42]
。这里,
xs
扩展为
42:xs
,然后
42:42:xs
,然后它停止,因为
take 2
只需要前两个元素,所以它停止


当然,当rhs是一个函数时,很明显,定义是递归的非常有用:
let fac=\n->如果n=0,那么1 else n*fac(n-1)
-这里你显然希望
fac
引用它自己,而不是之前对
fac
的定义,让表达式是递归的,所以当你有
让x=x*x
时,它都是相同的
x
,而不是来自外部作用域的。如果是相同的,为什么它不报告错误,因为
x
的查找失败?递归定义是Haskell的许多方面的核心,例如
映射f[]=[];映射f(x:xs)=fx:mapfxs
。我们希望
=
右侧的
映射的实例与
=
左侧的
映射的实例相同。甚至还有一个函数
fix
,它被定义为
fix f=let x=f x in x
,它实际上可以产生有价值的结果,一个微不足道的函数是
fix(1:)
,这会创建一个无限长的
1
s延迟列表,反复引用相同的
1
,这样它就不会在RAM中爆炸。你是说这是无限的,因为
x=x*x
的延迟计算?我认为如果您首先在
x=x*x
的RHS中计算
x
,那么就没有问题了。但是,如果您首先计算
x=x*x
而没有首先计算RHS中的
x
x
绑定到
x*x
,那么在
x*x
中计算
x
将导致此非终止,对吗?为什么会被否决?投票结束似乎也很不合理。我明白了,这正是我所想的。我可以把这看作是Haskell的惰性计算吗?似乎环境允许将非值绑定到变量。@xwang:是的,在严格的语言中,递归值定义是不可能的(除了一些特殊情况,如使用数据构造函数的循环定义,OCaml中的rec xs=42::xs
就是一个例子)。