#haskell #ghc #ghci
#исключение #haskell
Вопрос:
Есть ли способ заставить GHCi выдавать лучшие сообщения об исключениях, когда он обнаруживает во время выполнения, что вызов выдал значение, которое не соответствует сопоставлению с шаблоном функции?
В настоящее время он выдает номера строк функции, которая произвела неисчерпывающее совпадение с шаблоном, которое, хотя и полезно иногда, требует раунда отладки, который, как мне иногда кажется, выполняет один и тот же набор действий снова и снова. Поэтому, прежде чем я попытался собрать решение, я хотел посмотреть, существует ли что-то еще.
Сообщение об исключении, которое в дополнение к указанию номеров строк показывает, какой вызов оно пыталось выполнить?
Возможно ли это вообще?
Ответ №1:
Попробуйте включить предупреждения в ghci. Это позволяет получать предупреждения во время компиляции, которые вы можете получить с помощью ghc, передавая -W
, например. Вы можете сделать это несколькими способами:
ghci -fwarn-incomplete-patterns
Или Нил Митчелл описывает, как он устанавливает это в своем .ghci
. Вот соответствующий отрывок:
:set -fwarn-incomplete-patterns
Вы также можете вручную ввести это в ghci, но было бы больно делать это каждый раз, когда вы его запускаете. Введенный таким образом, он работает только для операторов, введенных в командной строке, а не для загрузки файлов :l
. Вместо этого вы можете поместить этот комментарий в начало файла, который вы хотите предупредить о неполных шаблонах:
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
Комментарии:
1. К сожалению, это не всегда предупреждает, насколько я могу видеть… Я только что попробовал и не повезло, спасибо в любом случае!
2. По-видимому, это относится только к операторам, введенным в ghc и не загруженным из файлов. Я обновил свой ответ, чтобы он тоже работал.
3. Как бы то ни было, когда я попробовал, прямой вызов GHCi с фактическими параметрами командной строки, казалось, включал его как для загруженных файлов, так и для операторов, введенных в командной строке.
Ответ №2:
Я признаю, что это что-то вроде ответа на ваш вопрос, но у меня сложилось впечатление, что среди опытных программистов Haskell существует общее мнение о том, что в первую очередь следует избегать неисчерпывающих шаблонов, вплоть до использования -Werror
для генерации ошибок вместо просто предупреждений.
Однако я не уверен, насколько хорошо это работает в сочетании с GHCi, особенно если вы пишете функции в командной строке вместо загрузки файла — я могу представить, что это больше мешает, чем помогает работать в интерактивном режиме. Однако запуск GHCi с соответствующими флагами командной строки, похоже, дает мне желаемый результат.
Если вам нужно более радикальное решение для неисчерпывающих шаблонов, вы всегда можете перенести Catch для работы с современными версиями GHC. Хех.
Кроме того, если вы используете неисчерпывающие шаблоны, потому что функция действительно, действительно, никогда не должна вызываться с некоторыми значениями, пропущенные случаи могут быть заполнены чем-то вроде error $ "function foo called with ridiculous arguments " show blahBlah
, если знание недопустимых аргументов было бы полезно. С другой стороны, вы можете попытаться переработать свой код или определить более специализированные типы данных, чтобы функции всегда могли делать что-то разумное с любым аргументом, отличным от нижнего.
В противном случае, я думаю, вы застряли в неудобной отладке.
Комментарии:
1. Это хороший момент, на данный момент я сомневаюсь, что смогу следовать этому правилу, но скоро мне предстоит сеанс рефакторинга, поэтому включение и исправление всего, что появляется, скоро будет в этом списке. Спасибо за подсказку, я не знал, что вы можете структурировать ошибку таким образом. Я сожалел о получении некоторых полезных ошибок, поскольку я не видел, чтобы этот стиль использовался. Кроме выдачи ошибки в виде ошибки «отказаться от отправки в функции foo»
2. @toofarsideways:
error
это просто функция, которая принимает произвольноеString
значение для сообщения об ошибке; вы можете делать все, что хотите, чтобы создать строку. Вы также можете заглянуть вDebug.Trace
модуль, если вы еще этого не сделали, для быстрой и грязной версии Haskell старомодной «отладки printf». Что касается использованияerror
, это, вероятно, плохой стиль для производственного кода, но подходит для разработки / тестирования.3. Спасибо, стоит изучить :). Я ломал голову над тем, как это сделать…