Вопрос о операторах ~ и @в Haskell
Что именно они делают? Я знаю одно возможное использование @(назначение имени в начале совпадения с шаблоном), но не удалось найти что-либо на ~.
Я нашел их в следующем фрагменте кода, взятом из http://www.haskell.org/haskellwiki/Prime_numbers, но в статье предполагается, что вы свободно владеете синтаксисом Haskell и не беспокоит объяснение своих эзотерических операторов (часть, с которой я запутался, является началом декларации для сита):
primesPT () = 2 : primes'
where
primes' = sieve [3,5..] primes' 9
sieve (p:xs) [email protected] ~(_:t) q
| p < q = p : sieve xs ps q
| True = sieve [x | x<-xs, rem x p /= 0] t (head t^2)
Любое объяснение (или ссылка на одно) о синтаксисе, используемом здесь, будет с благодарностью.
Ответы
Ответ 1
Оператор ~
делает совпадение ленивым. Обычно совпадение шаблонов оценивает аргумент, так как необходимо проверить, не сработал ли шаблон. Если вы префикс шаблона с ~
, оценка пока не будет необходимой. Эта функциональность часто используется в коде "Tying the knot" , где нужно ссылаться на структуры, которые еще не созданы. Если шаблон не удался после evaulation, результат будет undefined
.
Вот пример:
f (_:_) = True
f [] = False
g ~(_:_) = True
g [] = False
f []
дает False
, а g []
дает true, потому что первый шаблон всегда соответствует. (Вы действительно получаете предупреждение для этого кода)
Таким образом, вы можете видеть ~
как противоположность !
, который заставляет оценивать аргумент, даже если он не нужен.
Обратите внимание, что эти операторы только делают вещи строгими/ленивыми на уровне, на котором они применяются, а не рекурсивно. Например:
h ~((x,y):xys) = ...
Соответствие шаблону в кортеже строгое, но шаблон совпадений ленив.
Ответ 2
Это ленивое соответствие шаблону (также известное как неопровержимое совпадение с образцом, которое, по моему мнению, является лучшим именем).
По существу, ~(_:t)
всегда будет совпадать, даже если вход является пустым списком []
. Конечно, это опасно, если вы не знаете, что делаете:
Prelude> let f ~(_:t) = t in f []
*** Exception: <interactive>:1:4-15: Irrefutable pattern failed for pattern (_ : t)