简体   繁体   English

Haskell 中的无限递归

[英]Infinite recursion in Haskell

This question is essentially a duplicate of Debugging infinite loops in Haskell programs with GHCi .这个问题本质上是使用 GHCi 调试 Haskell 程序中的无限循环的副本 The author there solved it manually, though I'd like to know other solutions .那里的作者手动解决了它,但我想知道其他解决方案

(my particular problem) (我的特殊问题)

I have an arrow code which contains a recursive invocation,我有一个包含递归调用的箭头代码,

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

The errorArrow should make the recursive testAVFunctor not execute, since that will cause isError to return a Left (AVError "good error") which should in turn choose the passError route and bypass the recursive call. errorArrow应该使递归 testAVFunctor 不执行,因为这将导致 isError 返回一个Left (AVError "good error") ,它应该依次选择passError路由并绕过递归调用。

The very odd thing is that inserting "trace" calls at popular sites like the function composition results in the program emitting a finite amount of output, then freezing. 非常奇怪的是,在 function 组合等热门站点插入“跟踪”调用会导致程序发出有限数量的 output,然后冻结。 Not what I'd expect from an infinite term expansion problem. 不是我对无限项扩展问题的期望。 (see edit 1) (见编辑1)

I've uploaded my source code here if anyone is so curious.如果有人很好奇,我已经在这里上传了我的源代码。

EDIT 1编辑 1

I wasn't looking in the right place (if you care to look at the source, apparently avEither was looping).我没有找对地方(如果您想查看源代码,显然avEither正在循环)。 The way I got there was by compiling a binary, and running gdb :我到达那里的方式是编译一个二进制文件,然后运行 gdb

  • gdb Main gdb 主
  • r (runs code) r (运行代码)
  • Ctrl+C (send interrupt) . Ctrl+C (发送中断) The backtrace will be useless, but what you can do, is hit回溯将是无用的,但你能做的,是命中
  • s (step) . s (步骤) Then, hold down the enter key;然后,按住回车键; you should see a lot of method names fly by.您应该会看到很多方法名称飞过。 Hopefully one of them will be recognizable.希望其中一个能够被识别。

You can compile with ghc flag -O0 to disable optimization, which can reveal more method names.您可以使用 ghc 标志-O0进行编译以禁用优化,这可以显示更多方法名称。

EDIT 3编辑 3

Apparently, the proc x -> do block above was causing the code to generate combinators, which were calling the AVFunctor.arr lifting method to be called -- something in there must be violating laziness.显然,上面的proc x -> do块导致代码生成组合器,这些组合器正在调用要调用的AVFunctor.arr提升方法——其中一定有违反惰性的东西。 If I rewrite the top level function as如果我将顶层 function 重写为

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

then everything works fine.然后一切正常。 I guess it's time to try learning and using garrows (by a grad student here at Berkeley).我想是时候尝试学习和使用garrows (伯克利的一名研究生)。

My general takeaway from the experience is that ghci debugging can be frustrating.我从经验中得出的一般结论是 ghci 调试可能会令人沮丧。 For example, I managed to make the argument f of AVFunctor.arr show up as a local variable, but I can't get anything terribly informative from it:例如,我设法使AVFunctor.arr的参数f显示为局部变量,但我无法从中获得任何非常有用的信息:

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

Revised source code is here修改后的源代码在这里

Keep in mind that the meaning of (|||) depends on the arrow, and testAVFunctor is an infinite object of your arrow:请记住, (|||)的含义取决于箭头,而testAVFunctor是箭头的无限 object:

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

I'm not sure if you were aware of that.我不确定你是否意识到这一点。 Examine the definition of (|||) (or if there isn't one, left ) to see if it can handle infinite terms.检查(|||)的定义(或者如果没有,则left ),看看它是否可以处理无限项。 Also check (>>>) (er, (.) in modern versions I think).还要检查(>>>) (呃,我认为现代版本中的(.) )。 Make sure the combinators are not strict, because then an infinite term will diverge.确保组合子不是严格的,因为那样无限项会发散。 This may involve making patterns lazier with ~ (I have had to do this a lot when working with arrows).这可能涉及使用~使模式更懒惰(在使用箭头时我不得不这样做很多)。 The behavior you're seeing might be caused by too much strictness in one of the combinators, so it evaluates "far enough" to give some output but then gets stuck later.您看到的行为可能是由于其中一个组合器过于严格造成的,因此它评估“足够远”以给出一些 output 但后来卡住了。

Good luck.祝你好运。 You're into the deep subtleness of Haskell.您已深入了解 Haskell 的精妙之处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM