Подтвердить что ты не робот

Как отлаживать код Haskell?

У меня проблема. Я написал большую программу Haskell и всегда работает с небольшим вкладом. Теперь, когда я хочу протестировать его и создать большой вход, я всегда получаю сообщение:

HsProg: Prelude.head: empty list

Я использую Prelude.head много раз. Что я могу сделать, чтобы узнать больше или получить лучший вывод ошибки, чтобы получить строку кода, в которой это происходит?

4b9b3361

Ответ 1

Может быть полезна опция GHCi -fbreak-on-exception. Вот пример отладки сеанса. Сначала мы загружаем наш файл в GHCi.

$ ghci Broken.hs
GHCi, version 7.0.2: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
[1 of 1] Compiling Main             ( Broken.hs, interpreted )
Ok, modules loaded: Main.

Теперь включим -fbreak-on-exceptions и проследим наше выражение (main в этом случае для всей программы).

*Main> :set -fbreak-on-exception
*Main> :trace main
Stopped at <exception thrown>
_exception :: e = _

Мы остановились на исключении. Попробуем посмотреть код с помощью :list.

[<exception thrown>] *Main> :list
Unable to list source for <exception thrown>
Try :back then :list

Поскольку исключение произошло в Prelude.head, мы не можем напрямую смотреть на источник. Но, как сообщает GHCi, мы можем пойти :back и попытаться перечислить, что произошло раньше в трассировке.

[<exception thrown>] *Main> :back
Logged breakpoint at Broken.hs:2:23-42
_result :: [Integer]
[-1: Broken.hs:2:23-42] *Main> :list
1  
2  main = print $ head $ filter odd [2, 4, 6]
3  

В терминале нарушающее выражение filter odd [2, 4, 6] выделено жирным шрифтом. Таким образом, это выражение, которое оценивается в пустом списке в этом случае.

Подробнее о том, как использовать отладчик GHCi, см. Руководство пользователя GHC.

Ответ 2

Вы можете взглянуть на Haskell Wiki - Отладка, которая содержит много полезных подходов к вашей проблеме.

Одним из перспективных инструментов является LocH, что поможет вам найти вызов head в вашем коде, который вызвал ошибку пустого списка.

Лично я рекомендую safe пакет, который позволяет аннотировать большинство частичных функций из Prelude (и, следовательно, приводит к более сознательному использованию этих частичных функций ) или еще лучше, используйте общие варианты функций, таких как head, которые всегда возвращают результат (если входное значение было определено как минимум).

Ответ 3

Начиная с GHC 8, вы можете использовать модуль GHC.Stack или некоторые флаги компилятора профилирования, подробно описанные в блоге Simon.