Упражнение с неопровержимым/ленивым шаблоном в викикниге Haskell

На полпути сюда...

https://en.wikibooks.org/wiki/Haskell/Laziness

...это упражнение, в котором спрашивают о влиянии изменений на альтернативную реализацию функции head, которая использует неопровержимые шаблоны. Он дает определение head' следующим образом, отмечая, что он всегда будет возвращать undefined из-за неопровержимого совпадения первого уравнения:

head' :: [a] -> a
head' ~[]     = undefined
head' ~(x:xs) = x

Потом спрашивает:

  • Почему здесь не поможет изменение порядка уравнений на head'?
  • Если изменить первое уравнение, чтобы использовать обычный опровержимый образец, будет ли поведение head' отличаться от поведения head? Если да, то как?

В GHC 7.8.4 кажется, что изменение порядка «помогает», по крайней мере, в том смысле, что эта функция ведет себя как обычная частичная версия head, хотя и с другим исключением в случае пустого списка. Ответ на второй вопрос мне показался бы «нет», но, учитывая дополнение «если да, то как», мне кажется, что я тоже что-то упустил. Кто-нибудь может просветить меня? Ссылка на решения на странице, к сожалению, не распространяется на это упражнение.


person Mike Nunan    schedule 02.03.2016    source источник


Ответы (1)


Я не уверен, что викибук подразумевает под словом «помощь». Вы правы в том, что изменение порядка приведет к тому, что он будет вести себя как обычный head. Точно так же вы правы в том, что опровержение первого шаблона также приведет к тому, что он будет вести себя как head. Я собираюсь сказать, что эти вопросы запутаны; они определенно сбивают с толку.

Мы можем проверить эти ответы расчетом (включая расчет с помощью GHC):

head [] = ⊥
head (x:xs) = x
head ⊥ = ⊥

head' [] = ⊥
head' (x:xs) = ⊥
head' ⊥ = ⊥

head1 [] = ⊥
head1 (x:xs) = x
head1 ⊥ = ⊥

head2 [] = ⊥
head2 (x:xs) = x
head2 ⊥ = ⊥

head — стандартная версия библиотеки. head' — это версия из викиучебника. head1 — это версия с измененными пунктами. head2 — это версия, в которой первый образец является опровержимым совпадением с []. ⊥ читается как «нижний» и представляет собой не завершающееся или исключительное вычисление, т. е. undefined.

Чего я ожидал, так это примеров, подобных следующему, где есть тонкие, но существенные различия между опровержимыми и неопровержимыми шаблонами:

konst ~() = ()

konst' () = ()

partialId ~(x:xs) = x:xs

partialId' (x:xs) = x:xs
person Derek Elkins left SE    schedule 02.03.2016
comment
С запоздалой благодарностью за ваш полезный ответ и извинениями за любые другие нарушения этикета при возвращении сюда более 2 лет спустя, я снова просматривал заключительную часть вашего ответа и не могу найти способ получить другой результат. from partialId по сравнению с partialId' для любого ввода, который я могу придумать. Не могли бы вы указать мне на разницу, пожалуйста? (Я достаточно ясно вижу разницу между двумя вариантами konst.) - person Mike Nunan; 06.03.2018