Лучшее исключение для неисчерпывающих шаблонов в случае

#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. Спасибо, стоит изучить :). Я ломал голову над тем, как это сделать…