Что делает запятая в синтаксисе guard?
В кодовой базе, которую я читаю, я нашел объявление функции, подобное этому (некоторые части отсутствуют):
filepathNormalise :: BS.ByteString -> BS.ByteString
filepathNormalise xs
| isWindows, Just (a,xs) <- BS.uncons xs, sep a, Just (b,_) <- BS.uncons xs, sep b
= '/' `BS.cons` f xs
Что здесь делает запятая?
(Только в качестве бонуса, если кто-то с готовностью знает это: упоминается ли этот синтаксис в программировании на Haskell из первых принципов, и если да, то где? Как я не помню, читая об этом.)
2 ответа
Защита описана в разделе 3.13 Haskell 2010, " Выражения падежа" (этот раздел посвящен выражениям падежа, а не объявлениям верхнего уровня, но предположительно семантика одинакова):
guards → | guard1, …, guardn (n ≥ 1)
guard → pat <- infixexp (pattern guard)
| let decls (local declaration)
| infixexp (boolean guard)
Для каждого охраняемого выражения охранники, разделенные запятыми, пробуются последовательно слева направо. Если все они успешны, то соответствующее выражение оценивается в среде, расширенной привязками, введенными охранниками. То есть привязки, которые вводятся защитным устройством (либо с помощью предложения let, либо защитного шаблона), находятся в области действия следующих защитных элементов и соответствующего выражения. Если какой-либо из охранников отказывает, то это защищенное выражение терпит неудачу, и пробуется следующее защищенное выражение.
В простом случае запятая выполняет роль, аналогичную логической и. Но запятая является более сильной в том смысле, что каждый охранник может вводить новые привязки, которые используются последующими охранниками (начиная слева направо).
Запятые в охранниках достаточно редки (по моему опыту, по крайней мере), что я бы описал эту функцию как пустяки Хаскелла - совсем не обязательно писать (или, по большей части, читать) Хаскелл. Я подозреваю, что программирование на Haskell из первых принципов опускает его по этой причине.
Этот синтаксис недопустим в Haskell '98; это было добавлено в спецификацию языка в Haskell 2010. Это часть расширения языка "pattern guard".
https://prime.haskell.org/wiki/PatternGuards
Реальная полезность в этом заключается в том, что вы можете сопоставлять паттерны внутри охранного предложения. Синтаксическое изменение также имеет побочный эффект: вы можете объединять несколько логических терминов, используя запятые.
(Лично мне очень не нравится это расширение, и я немного шокирован тем, что оно превратилось в официальную спецификацию, но мы здесь...)