Подтвердить что ты не робот

Что такое "n + k patterns" и почему они запрещены в Haskell 2010?

Когда вы читаете запись в Википедии на Haskell 2010, я наткнулся на это:

-- using only prefix notation and n+k-patterns (no longer allowed in Haskell 2010)
factorial 0 = 1
factorial (n+1) = (*) (n+1) (factorial n)

Что они понимают под "n + k patterns"? Я предполагаю, что это вторая строка, но я не понимаю, что может быть не так. Может ли кто-нибудь объяснить, в чем проблема? Почему эти шаблоны n + k более разрешены в Haskell 2010?

4b9b3361

Ответ 1

Что такое n + k шаблонов? Возьмите gander:

$ ghci
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude> let f 0 = 0 ; f (n+5) = n
Prelude> :t f
f :: (Integral t) => t -> t
Prelude> f 0
0
Prelude> f 1
*** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f

Prelude> f 2
*** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f

Prelude> f 3
*** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f

Prelude> f 4
*** Exception: <interactive>:1:4-24: Non-exhaustive patterns in function f

Prelude> f 5
0
Prelude> f 6
1

В основном это особый случай сопоставления шаблонов, который работает только на числах и которые... ну, пусть просто вежливы и назовут это "неожиданными вещами" для этих чисел.

Здесь у меня есть функция f, которая имеет два предложения. Первое предложение соответствует 0 и только 0. Второе предложение соответствует любому значению типа Integral, значение которого равно 5 или больше. Связанное имя (n, в данном случае) имеет значение, равное номеру, который вы передали минус 5. Что касается того, почему они были удалены из Haskell 2010, я надеюсь, что теперь вы можете увидеть причину мышления. (Подсказка: рассмотрим принцип наименьшего удивления и как он может или не может применяться здесь.)


Отредактировано для добавления:

Естественный вопрос, который возникает теперь, когда эти конструкции запрещены, - "что вы используете для их замены?"

$ ghci
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude> let f 0 = 0 ; f n | n >= 5 = n - 5
Prelude> :t f
f :: (Num t, Ord t) => t -> t
Prelude> f 0
0
Prelude> f 1
*** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f

Prelude> f 2
*** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f

Prelude> f 3
*** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f

Prelude> f 4
*** Exception: <interactive>:1:4-33: Non-exhaustive patterns in function f

Prelude> f 5
0
Prelude> f 6
1

Из выражений типа вы заметите, что они не точно равны, но использование охранника "достаточно равно". Использование выражения n-5 в выражении может стать утомительным и подверженным ошибкам в любом коде, который использует его в нескольких местах. Ответ будет заключаться в использовании предложения where в строках:

Prelude> let f 0 = 0 ; f n | n >= 5 = n' where n' = n - 5
Prelude> :t f
f :: (Num t, Ord t) => t -> t
Prelude> f 0
0
Prelude> f 5
0
Prelude> f 6
1

Предложение where позволяет использовать вычисленное выражение в нескольких местах без риска опечатки. До сих пор остается досада необходимости редактировать значение границы (5 в этом случае) в двух отдельных местах в определении функции, но лично я чувствую, что это небольшая цена, чтобы заплатить за увеличение познавательного понимания.


Далее отредактирован, чтобы добавить:

Если вы предпочитаете выражения let над предложениями where, это альтернатива:

Prelude> let f 0 = 0 ; f n | n >= 5 = let n' = n - 5 in n'
Prelude> :t f
f :: (Num t, Ord t) => t -> t
Prelude> f 0
0
Prelude> f 5
0

И что это. Я действительно сделал это сейчас.

Ответ 2

Ссылка, предоставленная trinithis, верна; Модели n + k больше не включены в спецификацию Haskell.

Для получения дополнительной информации о моделях n + k в общем случае прокрутите примерно 3/5 пути вниз по этой странице в соответствие шаблонов или проверьте этот короткий post.