2015-04-16 5 views
8

Недавно я просмотрел фрагмент кода, который использовал Haskell's otherwise для соответствия шаблону в списке. Это поразило меня, как странно, так как:Haskell `в противном случае 'является синонимом` _`?

ghci> :t otherwise 
otherwise :: Bool 

Итак, я попытался следующие:

ghci> case [] of otherwise -> "!?" 
"!?" 

Я также пробовал с различными другими моделями различных типов и с -XNoImplicitPrelude включен (чтобы удалить otherwise из scope), и он все еще работает. Это должно произойти? Где это документировано?

+8

В прелюдии он определяет 'в противном случае = True'. Использование его в шаблоне соответствует только теням этого определения, вводя новую, более локальную переменную, которая также называется «иначе». Подобным примером является «случайное» затенение, которое может сбивать с толку »(==) ->« Y'know », ++ (==)', который возвращает «Y'know, теневое кодирование может сбивать с толку». – AndrewC

+6

С тех пор, как никто еще не сказал об этом, «иначе» предполагается использовать как защитное выражение, а не образец. 'case ... of pat | ... -> ... | в противном случае -> ... 'Теперь его определение как« Истина »важно. –

+0

@AndrewC, отличный пример! – luqui

ответ

16

Это не эквивалентно _, это эквивалентно любому другому идентификатору. То есть, если идентификатор используется в качестве шаблона в Haskell, шаблон всегда совпадает, и согласованное значение привязывается к этому идентификатору (в отличие от _, где он также всегда совпадает, но совпадающее значение отбрасывается).

Для большей ясности: идентификатор otherwise здесь не является особенным. Код также может быть x -> "!?". Кроме того, поскольку привязка никогда не используется, было бы разумнее использовать _, чтобы избежать предупреждения «неиспользуемого идентификатора» и сделать очевидным для читателя, что значение не имеет значения.

+5

'case [] в противном случае -> (в противном случае"!? ")' Is '([],"!? ")' - пример, показывающий, как работает привязка в этом случае. – Guvante

+0

Спасибо! Так что это просто еще одна переменная. Я должен был знать ... * Мягко бьет головой на стену *. – YellPika

+1

Просто запомните 'в противном случае = True'. Некоторые люди даже используют «True» вместо «в противном случае» в своем коде, который иногда читается странно, но также избегает непреднамеренной привязки. –

9

С тех пор, как никто еще не сказал об этом, в противном случае предполагается использовать в качестве защитного выражения, а не образец. case ... of pat | ... -> ... | в противном случае -> ... Теперь его определение как True важно. - Рейд Barton

Пример:

fact n acc 
    | n == 0 = acc 
    | otherwise = fact (n-1) $! (acc * n) 

Поскольку otherwise является True, что второй охранник всегда будет успешным.

Обратите внимание, что использование otherwise в шаблоне (в отличие от охранника) может смутить людей. Он также отключит предупреждение о скрытии имени, если GHC запускается с включенными соответствующими предупреждениями.