gat*_*ado 5 debugging haskell arrows infinite-loop ghci
这个问题基本上是使用GHCi在Haskell程序中调试无限循环的重复.那里的作者手动解决了它,虽然我想知道其他解决方案.
我有一个包含递归调用的箭头代码,
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)
如果有人这么好奇我在这里上传了我的源代码.
我没有找到正确的地方(如果你想看看源,显然avEither正在循环).我到那里的方法是编译二进制文件,然后运行gdb:
您可以使用ghc标志-O0进行编译以禁用优化,这可以显示更多方法名称.
显然,proc x -> do上面的块导致代码生成组合器,组合器调用AVFunctor.arr提升方法被调用 - 在那里必须有违反懒惰的东西.如果我将顶级函数重写为
testAVFunctor = errorArrow "good error" >>>
    isError >>> (passError ||| testAVFunctor)
一切正常.我想是时候尝试学习和使用garrows(伯克利的一名研究生).
我从经验中得到的一般看法是,ghci调试可能令人沮丧.例如,我设法让参数f的AVFunctor.arr显示为一个局部变量,但我不能从中得到任何可怕信息:
> :i f
f :: b -> c     -- <no location info>
修改后的源代码在这里
请记住, 的含义(|||)取决于箭头,并且testAVFunctor是箭头的无限对象:
testAVFunctor = proc x -> do
    ...
    (passError ||| proc x -> do
                       ...
                       (passError ||| proc x -> ...) -< trace "value of z" z)
        -< trace "value of z" z
我不确定你是否意识到这一点。检查 的定义(|||)(或者,如果没有的话,left),看看它是否可以处理无限项。还要检查(>>>)(呃,(.)我认为在现代版本中)。确保组合子不严格,因为这样无限项就会发散。这可能涉及使模式更加懒惰~(在使用箭头时我不得不经常这样做)。您看到的行为可能是由于其中一个组合器过于严格而引起的,因此它评估“足够远”以给出一些输出,但随后会卡住。
祝你好运。您已深入了解 Haskell 的精妙之处。