Haskell程序输出`<<loop>>`。

40

我写了一个Haskell程序,在列表上执行二分搜索。至少我以为它是这样。当我用ghc v7.6.3编译并运行程序时,我得到了以下输出:

progname: <<loop>>

这个输出到底是什么意思?是说我有一个无限循环,被 ghc 优化掉了吗?我该如何调试?


你是否了解ghci调试器?你也可以重新利用HPC来查找未被执行的代码,以缩小循环范围。 - Thomas M. DuBuisson
@ThomasM.DuBuisson GHCI 报错:Exception: <<loop>>。我猜编译输出的 progname: <<loop>> 是一个 STDERR 信息。这是否意味着我的程序陷入了无限循环? - recursion.ninja
4
是的,这是运行时系统(RTS)检测到无限循环(在某些情况下它可以这样做)。 - Fixnum
8
当它检测到评估一个特定构造函数需要评估该构造函数本身时,就会特别地出现无限循环。 - Carl
5
例如,您可以拥有完全定义的自我引用值。 例如 fibs = 0:scanl(+)1 fibs。 这就是为什么允许这样做的原因。 - Carl
显示剩余2条评论
1个回答

40

正如一些评论所说,这是Haskell RTS在运行时检测到无限循环。它不能总是检测到这些循环,但在简单的情况下可以。

例如:

x = x + 1

这段代码在编译时没有问题,但在运行时会引发异常。顺便提一下,这是一个异常, 特别的,如果你想的话,可以捕获它。但你可能不这样做。

那么为什么GHC会允许编译这段代码呢?好吧,因为如果我将+替换为:,那么表达式现在就可以正常终止了。(它表示一个包含1个元素的循环列表。)编译器无法在编译时判断哪些递归是合理的,哪些不是。RTS并非总能在运行时判断,但当它能够判断出有问题时,它会通过抛出异常来告诉你。


6
有没有办法强制Haskell输出它找到的哪个无限循环? - Bakuriu
2
很遗憾,你不能这样做。最好的方法是尝试捕获异常并打印出它来自哪里 - 但这需要你首先有一些想法从哪里开始查找。通常,循环错误是一些愚蠢的错误,比如拼写错误(例如,你想说 x = foo y 但不小心写成了 x = foo x)。 - MathematicalOrchid
10
如果您启用了性能分析编译,以下命令将告诉您异常抛出的位置:./progName +RTS -xc -RTS。@Bakuriu - recursion.ninja
@MathematicalOrchid,您能否在您的答案中添加您的示例(x = foo x)?我知道这是一个旧问题,但我刚从谷歌发送到这里,遇到了相同的错误,而且正如您所说,这是一个简单的问题。这可能对像我这样的Haskell新手提供价值(评论不是永久的)。 - jkeuhlen
@recursion.ninja的评论是那些查看这个问题的人所寻找的。 - cornuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接