Debugging Haskell:寻找不完整记录构造的来源

Debugging Haskell:寻找不完整记录构造的来源,debugging,haskell,ghc,ghci,Debugging,Haskell,Ghc,Ghci,我正在尝试用Haskell调试一个大型、复杂的程序,我并不是完全自己编写的 我试图打印我的数据结构来诊断一个bug,但是当我这样做时,我得到了以下错误:错误:Prelude.undefined。正如您所看到的,这个错误是非常没有信息的 我有理由相信这是来自一个我已经“部分”初始化的记录,我试图访问一个尚未设置值的字段 该程序(一个编译器)分布在两个cabal项目、一个库和一个使用该库的可执行文件上。这使得使用GHCI/cabal repl进行调试变得很困难:我无法在可执行文件上运行use-GHC

我正在尝试用Haskell调试一个大型、复杂的程序,我并不是完全自己编写的

我试图打印我的数据结构来诊断一个bug,但是当我这样做时,我得到了以下错误:
错误:Prelude.undefined
。正如您所看到的,这个错误是非常没有信息的

我有理由相信这是来自一个我已经“部分”初始化的记录,我试图访问一个尚未设置值的字段

该程序(一个编译器)分布在两个cabal项目、一个库和一个使用该库的可执行文件上。这使得使用GHCI/cabal repl进行调试变得很困难:我无法在可执行文件上运行use-GHCI,因为它不是错误的来源,但是手工重新创建可执行文件提供给库的输入太复杂了


我想知道:我能做些什么来获得更多关于错误记录创建位置的信息,错误的来源是什么字段,等等。是否有RTS选项或我可以用来提供错误输出的更多信息?

如果您在阴谋集团文件的ghc选项中使用
-Wall
,它将发出记录不完整的警告

module Foo where
data Bar = Bar { bar :: String, baz :: String }
f = Bar { baz = "foo" }

Foo.hs:5:5: Warning:
  Fields of ‘Bar’ not initialised: bar
  In the expression: Bar {baz = "foo"}
  In an equation for ‘f’: f = Bar {baz = "foo"}
Ok, modules loaded: Foo.
使用-Wall(或-Werror)编译是查找未初始化字段源的良好开端。但是,它可能不是错误的来源。缺少的记录字段初始化具有特定的错误消息:

Prelude> data A = A { a :: Int } deriving Show
Prelude> A {}
A {a = *** Exception: <interactive>:11:1-4: Missing field in record construction a
Prelude>data A=A{A::Int}派生显示
序曲>A{}
A{A=***异常::11:1-4:记录构造A中缺少字段
如果向记录字段添加严格性注释,则编译时将抛出错误:

Prelude> data A = A { a :: !Int } deriving Show
Prelude> let a = A { }

<interactive>:26:9:
    Constructor ‘A’ does not have the required strict field(s): a
    In the expression: A {}
    In an equation for ‘a’: a = A {}
Prelude>data A=A{A::!Int}派生显示
前奏曲>设a=a{}
:26:9:
构造函数“A”没有必需的严格字段:A
在表达式中:A{}
在‘a’的方程式中:a=a{}
查找错误源的另一个选项是在启用分析的情况下编译并传递-xc RTS标志

从GHC用户指南:

-xc(仅在编译程序进行评测时可用。)当程序中引发异常时,此选项会导致堆栈 要转储到stderr的跟踪

这对于调试特别有用:如果您的程序 抱怨一个head[]错误,而你却不知道是哪一位 导致它的代码的数量,使用-prof-fprof auto编译并运行 使用+RTS-xc-RTS将准确地告诉您该点的调用堆栈 提出了错误

输出中引发的每个异常都包含一个报告 程序(该程序在运行期间可能引发并捕获多个异常 它的执行),其中每个报告看起来如下所示:

***引发异常(由于+RTS-xc而报告),堆栈跟踪:GHC.List.CAF-->由:Main.polymonery.table_search计算,
从Main.polynomy.theta_索引调用,从 Main.polyman,从Main.zonal_压力调用,从 Main.make_pressure.p,从Main.make_pressure调用,从 Main.compute\u initial\u state.p,从调用 Main.compute\u初始状态,从Main.CAF调用


我不知道你真的可以得到堆栈跟踪。遗憾的是,你需要重新编译整个Haskell平台以进行评测,但是,嘿……谢天谢地,我过去在评测方面遇到的麻烦已经够多了,我已经让我的整个沙盒在启用评测的情况下编译了。。。