#haskell #recursion #non-exhaustive-patterns
#haskell #рекурсия #неисчерпывающие-шаблоны
Вопрос:
Я пытаюсь написать функцию, которая дает мне расстояние между каждым районом в моем списке. Функция distance
дает мне расстояние между двумя районами как Int
из заданного массива, и я хочу просмотреть весь список, чтобы суммировать расстояние между каждым районом и его последователем в списке.
Но я получаю
Неисчерпывающие шаблоны
сообщение об ошибке. Что я упустил из виду? Функция distance
работает так, как должна.
lengthr :: [district] -> Int
lengthr [] = 0
lengthr (a:b:as) = (distance a b) lengthr (b:as)
Комментарии:
1. Что должно произойти, если вы предоставите
lengthr
список, содержащий ровно один элемент?2. Следующего пункта назначения для перехода не будет, поэтому расстояние должно выводить 0.
3. Видите ли вы какие-либо строки в вашем текущем определении функции, которые могли бы это сделать? Если нет, можете ли вы придумать строку, которую вы могли бы добавить?
4. В будущем компилируйте с предупреждениями об использовании
-Wall
: вы обнаружите ошибку во время компиляции, и в сообщении об ошибке будут указаны случаи, которые вы упускаете.
Ответ №1:
Я добавил строку lengthr [a] = 0
в свой код, чтобы скрыть случай, когда остался только один элемент, и теперь код работает так, как задумано!
Ответ №2:
Как вы упомянули в своем собственном ответе, вы упустили случай одного элемента.
Более общим решением является включение всеобъемлющего шаблона _
после всех конкретных случаев, которые вы хотите обработать.
lengthr:: [district] -> Int
lengthr (a:b:as) = (distance a b) lengthr (b:as)
lengthr _ = 0
Это более традиционный способ обработки ситуаций по умолчанию.
В ситуациях, когда результат содержится в a Monad
, который имеет семантику ошибки (например, Either e
и Maybe
), вы можете сделать случай по умолчанию ошибкой вместо того, чтобы потенциально игнорировать ошибку.
lengthr:: [district] -> Either String Int
lengthr (a:b:as) = do
next <- lengthr (b:as)
Right $ (distance a b) next
lengthr [_] = Right 0
lengthr _ = Left "empty list"