#haskell
Вопрос:
Будучи новичком, я работаю над примером функции с пошаговым определением.
pts 1 = 10
pts 2 = 6
pts x = x
Приведенный выше код работает так, как я и ожидал. Однако, когда я попытался изменить порядок на
pts x = x
pts 1 = 10
pts 2 = 6
Я получил предупреждение
предупреждение: [-Woverlapping-шаблоны] Совпадение шаблонов является избыточным
и последние два утверждения, похоже, игнорируются компилятором. Мне не удалось найти ответ в Google, я был бы признателен за ссылку на объяснение.
Комментарии:
1. Написать алгоритм, который проверяет, все ли шаблоны непересекающиеся, сложно, а писать шаблоны, которые все непересекающиеся, раздражает. Поэтому вы должны согласиться с тем, что некоторые шаблоны перекрываются, и язык должен указывать, что происходит, когда они это делают. Примерить их в том порядке, в каком их написал программист, — один из естественных вариантов; есть и другие, но большинство из них гораздо сложнее указать и правильно использовать.
2. @DanielWagner ваш комментарий был бы хорошим ответом.
3. @DanielWagner Я полагаю, что можно было бы автоматически упорядочивать шаблоны от наиболее специфичных до наименее специфичных (хотя в менее тривиальных примерах для этого потребуется какое-то лексикографическое соглашение). Только… почему ? Простая схема сверху вниз работает отлично, ее легко понять и отладить.
4. @CalumHalpin, может быть. Я не уверен. С этими «почему происходит X?» на вопросы всегда есть два уровня ответа: «какое правило объясняет такое поведение?» и «почему было выбрано это правило?». Существующий принятый ответ является ответом на первый, что заставляет меня думать, что, хотя он и интересен, ответ на последний на самом деле не имеет отношения к исходному вопросу.
5. @DanielWagner это вполне может иметь отношение к кому-то, кто столкнется с этим вопросом в будущем. В любом случае, это ответ, и ему не место в комментариях.
Ответ №1:
В Haskell шаблоны в определениях функций, подобных этому, проверяются сверху вниз. Итак, ваш первый пример такой же, как:
pts x =
if x == 1 then 10
else if x == 2 then 6
else x
И ваше второе определение похоже на:
pts x =
if True then x
else if x == 1 then 10
else if x == 2 then 6
else undefined
Очевидно, что в этом втором примере всегда берется первая ветвь, остальные являются избыточными.
Ответ №2:
Хаскелл просматривает шаблоны сверху вниз и выбирает первый, который соответствует входным данным. В этом случае x
соответствует любому входу, потому что это просто обычная переменная, поэтому, если она сверху, она всегда выбирается сразу, а другие шаблоны даже не рассматриваются. Это такое решение:
pts x = if True then x
else if ... -- irrelevant
Если он находится внизу, он рассматривается только после того, как другие шаблоны потерпели неудачу, и поскольку они соответствуют конкретно только одному числу, это будет происходить чаще, чем нет.