调试 Haskell 代码的更好方法是什么?

exc*_*nge 6 debugging haskell

这里提出了一个类似的问题,但已经有十多年了,我希望在此期间已经取得了一些进展,现在可以产生不同的答案。

现在我正在使用 VSCode 并安装了“Haskell GHCi 调试适配器 Phoityne”。它可以工作,但由于 Haskell 的惰性(以及纯代码和 IO 代码的分离以及 Haskell 的函数性质),调试代码仍然很困难。

似乎已经提出了针对此类问题的一些解决方案。例如,我发现这篇文章比较了 Haskell 中的调试技术,并命名了几个试图通过引入函数“观察”来改善体验的包。除此之外,HoodHoedHat 都被命名了,我还在hackage 上发现了debug 。

然而,不幸的是,我没有让它们中的任何一个工作。FPretty安装 Hood 时,我收到错误消息,指出它具有与较新版本的基础包不兼容的依赖项(自 2018 年以来,这已作为问题提交)。霍德也面临同样的问题。安装 Hat 时,我遇到了很多错误,首先是抱怨缺少模块,然后在解释程序时调试崩溃。

结果,我无法测试其中任何一个。然而,我真正想要的是一个图形调试器(最好是 VSCode 中已实现的调试器的改进版本!),它跳转到正在检查的源代码行,然后显示一个小窗口,逐步展开递归(或者无需评估,或者更好的是,在递归完成(即在实际评估之前)提供一些逐步评估的选项),类似于此 wiki 文章中如何显示foldr 的效果。

上述软件包之一可以执行此操作吗?对于 Haskell 社区来说,为 VSCode 提供这样的功能来改善生态系统并吸引新人不是很好吗?或者这已经可能了,但我只是不知道如何正确配置 Phoityne?或者你有完全不同的方法来有效地调试 Haskell 吗?您的工作流程是什么?

Vit*_*adi 3

我从未设法使现有的调试解决方案正常工作,因此我只使用自定义 ghci 命令,并:set stop :status在每个断点停止处很好地显示变量和其他有用信息。

在 ghci 中:
:br someFunction- 在 someFunction 处设置断点
:br SomeModule.someFunction- 在模块中的函数处设置断点
:br SomeModule 150- 在特定行处设置断点
:stl- 本地步(步过)
:st - 单步(步入)
:status- 显示状态

内容~/.ghci

-- Fancy debugging
_nl = "putStrLn \"\"\n"
_history = "putStrLn \"HISTORY:\"\n :history \n"
_context = "putStrLn \"CONTEXT:\"\n :sh context\n"
_breaks = "putStrLn \"BREAKS:\"\n :sh breaks\n"
_bindings = "putStrLn \"BINDINGS:\"\n :sh bindings\n"
_list = "putStrLn \"LIST:\"\n :list\n"
_status = \_ -> return $ ":!clear\n " ++ _breaks ++ _nl ++ _history ++ _nl ++ _bindings ++ _nl ++ _context ++ _nl ++ _list ++ _nl

-- Useful commands
:def hoogle \x -> return $ ":!hoogle \"" ++ x ++ "\""
:def hinfo \x -> return $ ":!hoogle --info \"" ++ x ++ "\""
:def stl \x -> return $ ":steplocal " ++ x
:def status _status
:def fprint \x -> return $ ":force " ++ x ++ "\n" ++ "print " ++ x
:def fpprint \x -> return $ ":force " ++ x ++ "\n" ++ "pPrint " ++ x

-- Show status on breakpoint
:set stop :status
Run Code Online (Sandbox Code Playgroud)

除此之外,还有 haskell-language-server 和 ghcid 对于更快的错误和类型检查很有用。