Вопрос об операторах ~ и @ в Haskell - PullRequest
14 голосов
/ 22 сентября 2011

Что именно они делают? Я знаю одно возможное использование @ (присваивание имени в начале сопоставления с образцом), но не смог найти ничего в ~.

Я нашел их в следующем фрагменте кода, взятом из http://www.haskell.org/haskellwiki/Prime_numbers,, но в статье предполагается, что вы свободно владеете синтаксисом Haskell и не пытаетесь объяснить его эзотерические операторы (часть, о которой я запутался, это начало объявления для сита ):

primesPT () = 2 : primes'
  where 
    primes' = sieve [3,5..] primes' 9
    sieve (p:xs) ps@ ~(_:t) q
       | p < q   = p : sieve xs ps q
       | True    =     sieve [x | x<-xs, rem x p /= 0] t (head t^2)

Будем весьма благодарны за любые объяснения (или ссылки на них) о синтаксисе, использованном здесь.

Ответы [ 2 ]

11 голосов
/ 22 сентября 2011

Оператор ~ делает матч ленивым.Обычно сопоставление с шаблоном оценивает аргумент, так как необходимо проверить, не неудачно ли шаблон.Если вы префикс шаблона ~, оценка не будет, пока он не понадобится.Эта функциональность часто используется в коде «Связывание узла» , где необходимо ссылаться на структуры, которые еще не созданы.Если при эваляции шаблон терпит неудачу, результат равен undefined.

. Вот пример:

f (_:_) = True
f []    = False

g ~(_:_) = True
g []     = False

f [] дает False, тогда как g [] дает true, потому чтопервый шаблон всегда совпадает.(Вы действительно получаете предупреждение для этого кода)

Тем не менее, вы можете видеть ~ как противоположность !, что вызывает оценку аргумента, даже если он не нужен.

Обратите внимание, что эти операторы делают вещи строгими / ленивыми только на том уровне, на котором они применяются, а не рекурсивно.Например:

h ~((x,y):xys) = ...

Сравнение шаблонов на кортеже строгое, но шаблон "против" ленив.

9 голосов
/ 22 сентября 2011

Это совпадение с ленивым образцом (также известное как неопровержимое совпадение с шаблоном , которое, я думаю, является лучшим именем).

По сути, ~(_:t) всегда будет совпадать, даже если в качестве ввода используется пустой список []. Конечно, это опасно, если вы не знаете, что делаете:

Prelude> let f ~(_:t) = t in f []
*** Exception: <interactive>:1:4-15: Irrefutable pattern failed for pattern (_ : t)
...