2015-07-06 6 views
3

Я пытаюсь отлаживать большую сложную программу в Haskell, которую я не полностью написал сам.Haskell: Поиск источника незавершенного построения записи

Я пытаюсь распечатать свои структуры данных, чтобы диагностировать ошибку, но когда я это сделаю, я получаю следующую ошибку: error: Prelude.undefined. Как вы можете видеть, эта ошибка крайне неинформативна.

Я уверен, что это происходит из записи, которую я «частично» инициализировал, где я пытаюсь получить доступ к полю, значение которого не было установлено.

Программа (компилятор) распространяется на два проекта cabal, библиотеку и исполняемый файл, который использует эту библиотеку. Это делает отладку с использованием GHCI/cabal-repl hard: я не могу запустить GHCi в исполняемом файле, потому что это не источник ошибки, но воссоздать ввод, который предоставляет исполняемый файл библиотеке, слишком сложно сделать вручную.

Мне интересно: что я могу сделать, чтобы получить больше информации о том, где создается некорректная запись, какое поле является источником ошибки и т. Д. Есть ли опция RTS или что-то, что я могу использовать, чтобы дать больше информация для вывода ошибок?

ответ

6

Сборка с -Wall (или -Werror) является хорошим первым стартом к нахождению источника неинициализированного поля. Однако это может быть не источник ошибки. Недостающие поля записи initializions имеет конкретное сообщение об ошибке:

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 (Only available when the program is compiled for profiling.) When an exception is raised in the program, this option causes a stack trace to be dumped to stderr.

This can be particularly useful for debugging: if your program is complaining about a head [] error and you haven't got a clue which bit of code is causing it, compiling with -prof -fprof-auto and running with +RTS -xc -RTS will tell you exactly the call stack at the point the error was raised.

The output contains one report for each exception raised in the program (the program might raise and catch several exceptions during its execution), where each report looks something like this:

*** Exception raised (reporting due to +RTS -xc), stack trace: GHC.List.CAF --> evaluated by: Main.polynomial.table_search,
called from Main.polynomial.theta_index, called from Main.polynomial, called from Main.zonal_pressure, called from Main.make_pressure.p, called from Main.make_pressure, called from Main.compute_initial_state.p, called from Main.compute_initial_state, called from Main.CAF ...

+1

Я понятия не имел, вы могли бы на самом деле получить трассировку стека. Жаль, что вам нужно перекомпилировать всю платформу Haskell для профилирования, но эй ... – MathematicalOrchid

+0

К счастью, у меня было достаточно прошлых проблем с профилированием, что у меня уже была вся моя песочница, скомпилированная с профилированием ... – jmite

7

Если вы используете -Wall в параметрах ghc вашего файла cabal, он даст предупреждение о неполных записях.

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. 
Смежные вопросы