Отладка кода на Haskell с помощью Debug.Trace

12 октября 2012

Что ни говори, а отладочный вывод был и остается одним из самых простых и часто используемых способов отладки. Но как прикажите использовать его в Haskell при написании чистых функций? Временно оборачивать функцию в монаду IO, а по завершении отладки возвращать код к прежнему состоянию? Разумеется, нет!

Есть такой «читерный» модуль под названием Debug.Trace. Он идет вместе с GHC. В этом модуле объявлено несколько функций для отладочного вывода. Они кажутся чистыми, но на самом деле, по понятным причинам, такими не являются.

Рассмотрим эти функции.

trace :: String -> a -> a

Функция trace выводит строку, переданную первым аргументом, и возвращает то, что было передано вторым аргументом. Как видите, эта функция притворяется чистой, но в действительности у нее есть побочный эффект.

traceShow :: Show a => a -> b -> b

Функция traceShow аналогична trace, только первый аргумент преобразуется в строку с помощью функции show. Чтобы вывести с помощью traceShow несколько значений, можно, например, объединить их в кортеж. Как и trace, функция traceShow возвращает свой второй аргумент.

traceStack :: String -> a -> a

Функция traceStack аналогична функции trace, но помимо своего первого аргумента она также выводит стек вызовов, если он доступен. Чтобы traceStack выводила стек вызовов, программа должна быть собрана с флагом -prof (если вы используете GHC).

traceIO :: String -> IO ()

Функция traceIO делает практически то же самое, что putStrLn. Пожалуй, единственное польза от нее заключается в том, что эту функцию легко найти по имени и затем избавиться от ее вызова.

Пример использования Debug.Trace:

$ ghci
> import Debug.Trace
> let func x = trace ( "x = " ++ show x) $  x + 1
> func 1
x = 1
2

Итак, если раньше для поиска ошибок мы имели статическую типизацию, REPL, логи, если они ведутся, и модульные тесты, если вы их пишите, то теперь в нашем арсенале появилось и традиционное распихивание варнов по всему коду. Само собой разумеется, что использовать Debug.Trace следует только во время отладки!

А как вы отлаживаете свой код на Haskell?

Метки: , , , .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.