Haskell:找到不完整记录构建的来源

时间:2015-07-06 06:10:36

标签: debugging haskell ghc ghci

我正在尝试在Haskell中调试一个庞大而复杂的程序,我自己并没有完全写出来。

我正在尝试打印我的数据结构来诊断错误,但是当我这样做时,我收到以下错误:error: Prelude.undefined。如您所见,此错误非常缺乏信息。

我有理由相信这是来自我已“部分”初始化的记录,我正在尝试访问其值尚未设置的字段。

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

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

2 个答案:

答案 0 :(得分:7)

如果您在cabal文件的ghc-options中使用-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.

答案 1 :(得分:6)

使用-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 } 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 {}

查找错误源的另一个选项是在启用性能分析的情况下进行编译并传递-xc RTS标志。

来自GHC用户指南: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/runtime-control.html

  

-xc(仅在编译程序进行性能分析时可用。)当程序中引发异常时,此选项会导致堆栈   追踪将被倾倒到stderr。

     

这对于调试特别有用:如果您的程序是   抱怨head []错误并且你没有得到任何线索   代码导致它,使用-prof -fprof-auto进行编译并运行   使用+ RTS -xc -RTS将准确告诉您该点的调用堆栈   提出错误。

     

输出包含一个报告,用于引发的每个异常   程序(该程序可能会提出并捕获几个例外   它的执行),每个报告看起来像这样:

     

***引发异常(由于+ RTS -xc报告),堆栈跟踪:GHC.List.CAF - &gt;评估者:Main.polynomial.table_search,
  从Main.polynomial.theta_index调用,调用来自   Main.polynomial,从Main.zonal_pressure调用,调用   Main.make_pressure.p,从Main.make_pressure调用,调用来自   Main.compute_initial_state.p,调用自   Main.compute_initial_state,从Main.CAF调用...