【问题标题】:Infinite recursion in HaskellHaskell中的无限递归
【发布时间】:2011-08-16 08:12:54
【问题描述】:

这个问题本质上是Debugging infinite loops in Haskell programs with GHCi 的重复。 那里的作者手动解决了,不过我想知道其他解决方案

(我的特殊问题)

我有一个包含递归调用的箭头代码,

testAVFunctor = proc x -> do
    y <- errorArrow "good error" -< x
    z <- isError -< y
    (passError ||| testAVFunctor) -< trace "value of z" z

errorArrow 应该使递归 testAVFunctor 不执行,因为这将导致 isError 返回一个 Left (AVError "good error"),这应该反过来选择 passError 路由并绕过递归调用。

非常奇怪的是,在函数组合等流行站点插入“跟踪”调用会导致程序发出有限数量的输出,然后冻结。不是我对无限项扩展问题的期望。(见编辑 1)

如果有人好奇,我已经上传了我的源代码here

编辑 1

我没有找对地方(如果您想查看源代码,显然 avEither 正在循环)。我到达那里的方法是编译一个二进制文件,然后运行 ​​gdb

  • gdb 主要
  • r (运行代码)
  • Ctrl+C (发送中断)。回溯将是无用的,但你能做的,就是命中
  • s (步骤)。然后,按住回车键;您应该会看到很多方法名称飞过。希望其中一个能被认出来。

您可以使用 ghc flag -O0 进行编译以禁用优化,这可以显示更多方法名称。

编辑 3

显然,上面的 proc x -&gt; do 块导致代码生成组合器,它们正在调用 AVFunctor.arr 提升方法被调用——其中的某些东西一定违反了惰性。如果我将顶层函数重写为

testAVFunctor = errorArrow "good error" >>>
    isError >>> (passError ||| testAVFunctor)

然后一切正常。我想是时候尝试学习和使用garrows(由伯克利的一名研究生提供)。

我从经验中得出的一般结论是 ghci 调试可能会令人沮丧。例如,我设法使AVFunctor.arr 的参数f 显示为局部变量,但我无法从中获得任何非常有用的信息:

> :i f
f :: b -> c     -- <no location info>

修改后的源代码为here

【问题讨论】:

  • 在链接的重复问题上,作者手动解决了,其他评论那里的用户已经询问了出处。所以,我开始了这个问题。我当然正在调试它,并会在我发现更多信息时更新此页面。如果有人知道自动技术,我将不胜感激——我是一个 haskell 新手。
  • 嗯,我认为 gdb 不能与基于 hackage.haskell.org/trac/ghc/wiki/Debugging/… 的 ghc 一起工作
  • 您看不到真正的堆栈跟踪,但您可以看到一些方法名称。对于此示例,请下载原始 AVFunctor.zip(编辑部分之前的链接),然后运行 ​​ghc -O0 --make Main.hsgdb Mainrctrl+cs,如上。你会看到类似这样的东西,pastebin.com/xSJ9uMn3

标签: debugging haskell infinite-loop ghci arrows


【解决方案1】:

请记住,(|||) 的含义取决于箭头,而testAVFunctor 是箭头的无限对象:

testAVFunctor = proc x -> do
    ...
    (passError ||| proc x -> do
                       ...
                       (passError ||| proc x -> ...) -< trace "value of z" z)
        -< trace "value of z" z

我不确定你是否意识到这一点。检查(|||) 的定义(或者如果没有,left),看看它是否可以处理无限项。还要检查(&gt;&gt;&gt;)(呃,我认为是现代版本的(.))。确保组合子不是严格的,因为那样无限项会发散。这可能涉及使用~ 使模式更懒惰(在使用箭头时我不得不这样做很多)。您看到的行为可能是由于其中一个组合器过于严格造成的,因此它评估“足够远”以提供一些输出,但稍后会卡住。

祝你好运。您已深入了解 Haskell 的精妙之处。

【讨论】:

  • 谢谢,我需要它:)。我正在检查(|||);它可能在那里的某个地方。 ~ 在一个更简单的例子中我很幸运,谢谢!
猜你喜欢
  • 2016-09-11
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-14
相关资源
最近更新 更多