【问题标题】:Haskell program outputs `<<loop>>`Haskell 程序输出 `<<loop>>`
【发布时间】:2014-02-25 15:08:07
【问题描述】:

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

progname: <<loop>>

这个输出到底是什么意思?这是否意味着我有一个无限循环,ghc 优化了?我应该如何调试这个?

【问题讨论】:

  • 你知道 ghci 调试器吗?您还可以重新利用 HPC 来找出哪些代码没有被执行,以此来缩小循环范围。
  • @ThomasM.DuBuisson GHCI 提出:Exception: &lt;&lt;loop&gt;&gt;。我假设编译后的输出 progname: &lt;&lt;loop&gt;&gt; 是和 STDERR 消息。这是否意味着我有一个无限循环?
  • 是的,这是 RTS(运行时系统)检测到无限循环(在某些情况下它可以做到)。
  • 特别是当它检测到在评估特定构造函数时导致的无限循环需要评估该构造函数。
  • @awashburn 您可以拥有完全定义的自引用值。 fibs = 0 : scanl (+) 1 fibs,例如。这就是它被允许的原因。

标签: debugging haskell compilation ghc haskell-platform


【解决方案1】:

正如几位 cmets 所说,这是 Haskell RTS 在运行时检测到无限循环。它cannot always detect such loops,但在简单的情况下它可以。

例如,

x = x + 1

会编译得很好,但会在运行时引发异常。 (顺便说一句,这是一个异常 - 特别是,如果你愿意,你可以捕捉它。但你可能不“想要”。)

那么为什么 GHC 还要让它编译呢?好吧,因为如果我将+ 替换为:,那么表达式现在终止就好了。 (它表示一个 1 元素循环列表。)编译器无法在编译时判断什么是合理递归,什么不是合理递归。 RTS 不能总是在运行时判断;但是当它可以告诉你有什么问题时,它会通过向你抛出异常来让你知道。

【讨论】:

  • 有没有办法强制 Haskell 也输出它找到的 which 无限循环?
  • @Bakuriu 遗憾的是没有。你能做的最好的事情是尝试捕捉异常并打印出你从哪里捕捉到它——但这需要你首先知道从哪里开始寻找。通常循环错误与拼写错误一样愚蠢(例如,您的意思是x = foo y,但不小心写成了x = foo x)。
  • @Bakuriu 如果您在启用分析的情况下进行编译,以下将告诉您异常是在哪里引发的:./progName +RTS -xc -RTS
  • @MathematicalOrchid 您能否将您的示例(x = foo x)添加到您的答案中?我知道这是一个老问题,但我刚从谷歌那里收到同样的错误,这是一个简单的问题,就像你说的那样。这可能会为像我这样的其他 Haskell 新手提供价值(而 cmets 不会永远存在)。
猜你喜欢
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
  • 1970-01-01
相关资源
最近更新 更多