关于 Haskell 中 ~ 和 @ 运算符的问题

14

他们具体做什么?我知道“@”的一个可能用途是在模式匹配开始时分配名称,但我没有找到任何关于“~”的东西。

我在以下代码片段中找到了它们,取自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)

如果有任何关于这里使用的语法的解释(或链接)将不胜感激。


1
http://haskell.org/haskellwiki/Keywords 是一个查找无法通过谷歌搜索到的东西的不错的地方。 - Ben Millwood
2个回答

11

运算符~将匹配变为惰性的。通常,模式匹配会评估参数,因为需要检查模式是否失败。如果在模式前加上~,则直到需要时才会进行评估。这个功能经常用在"绕过障碍"代码中,在那里需要引用尚未创建的结构。如果在评估时模式失败,则结果是undefined

以下是示例:

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

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

f []返回False,而g []返回true,因为第一个模式始终匹配。(实际上,您会收到此代码的警告)

话虽如此,您可以将~看作!的相反,后者即使不需要也会强制评估参数。

请注意,这些运算符仅在它们应用的级别上使事情变得严格/惰性,并非递归地。例如:

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

元组的模式匹配是严格的,但 cons 模式是惰性的。


9

这是一个惰性模式匹配(也称为不可反驳的模式匹配,我认为这更好)。

实际上,~(_:t)将始终匹配,即使输入是空列表[]。当然,如果你不知道你在做什么,这很危险:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接