шаблоны против охранников: иначе не совпадает? - PullRequest
4 голосов
/ 05 июля 2011

Следующие две функции ведут себя по-разному, если задана пустая строка:

guardMatch l@(x:xs) 
    | x == '-'        = "negative " ++ xs
    | otherwise       = l

patternMatch ('-':xs) = "negative " ++ xs
patternMatch l        = l

Вот мой вывод:

*Main> guardMatch ""
"*** Exception: matching.hs:(1,1)-(3,20): Non-exhaustive patterns in function guardMatch

*Main> patternMatch ""
""

Вопрос : почему закрытие «иначе» не захватывает пустую строку?

Ответы [ 3 ]

13 голосов
/ 05 июля 2011

otherwise находится в области действия шаблона l@(x:xs), который может соответствовать только непустой строке. Это может помочь увидеть, что это (эффективно) переводит внутренне:

guardMatch   l = case l of
                   (x  :xs) -> if x == '-' then "negative " ++ xs else l
patternMatch l = case l of
                   ('-':xs) ->                  "negative " ++ xs
                   _        ->                                         l

(На самом деле, я думаю, что if переводится на case + охрану, а не наоборот).

9 голосов
/ 05 июля 2011

Страж всегда оценивается после паттерна. Это - охранник проверяется, если шаблон успешен. В вашем случае шаблон (x:xs) исключает пустую строку, поэтому охранники даже не пробуются, так как шаблон не выполняется.

3 голосов
/ 06 июля 2011

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

guardMatch l@(x:xs) 
    | x == '-'        = "negative " ++ xs
    | otherwise       = [x]

Что бы вы ожидали от guardMatch ""?

...