这个问题本质上是使用 GHCi 在 Haskell 程序中调试无限循环的副本。那里的作者手动解决了它,但我想知道其他解决方案。
(我的特殊问题)
我有一个包含递归调用的箭头代码,
testAVFunctor = proc x -> do
y <- errorArrow "good error" -< x
z <- isError -< y
(passError ||| testAVFunctor) -< trace "value of z" z
应该使递归 testAVFunctor 不执行,因为这errorArrow
将导致 isError 返回 a Left (AVError "good error")
,它应该依次选择passError
路由并绕过递归调用。
非常奇怪的是,在函数组合等流行站点插入“跟踪”调用会导致程序发出有限数量的输出,然后冻结。不是我对无限项扩展问题的期望。(见编辑1)
如果有人很好奇,我已经在这里上传了我的源代码。
编辑 1
我没有找对地方(如果您想查看源代码,显然avEither正在循环)。我到达那里的方式是编译一个二进制文件并运行 gdb:
- gdb 主要
- r (运行代码)
- Ctrl+C (发送中断)。回溯将是无用的,但你能做的,是命中
- s (步骤)。然后,按住回车键;您应该会看到很多方法名称飞过。希望其中一个能够被识别。
您可以使用 ghc 标志进行编译-O0
以禁用优化,这可以显示更多方法名称。
编辑 3
显然,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>
修改后的源代码在这里