Вопрос об операторах ~ и @ в Haskell

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

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

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)

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


person damien    schedule 21.09.2011    source источник
comment
haskell.org/haskellwiki/Keywords — неплохое место для поиска информации, недоступной для Google.   -  person Ben Millwood    schedule 29.09.2011


Ответы (2)


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

Вот пример:

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

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

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

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

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

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

Сопоставление шаблона в кортеже является строгим, а шаблон cons — ленивым.

person fuz    schedule 21.09.2011

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

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

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