在Haskell中,这个@(Sentence string _)= do`是什么意思?

Cod*_*ein 2 haskell

这是我分配给调试的Haskell程序的一部分:

process :: Sentence -> IO ()
process this@(Sentence string _) = do
  render string
  render "==>"
  render $ translate this

render = putStrLn

data Sentence = Sentence String Task

translate :: Sentence -> String     ; Incomplete Definition
translate (Sentence string task)
  | ...

  | ...

  | ...

  | ...
Run Code Online (Sandbox Code Playgroud)

我不理解或认识到的这个程序的唯一部分是process this@(Sentence string _) = do 我以前从未见过的this@那条线,而且我也不太确定下划线(Sentence string _)是什么意思.

小智 7

this@是'as-pattern'的_一个例子,而是一个通配符模式的例子.当我们不关心模式中该点的值时使用通配符模式,因此_模式中的任何一个都匹配,并且它不绑定任何本地名称/变量.

另一方面,当我们想要绑定一个额外的本地名称/变量同时也匹配它时,我们使用as模式.你可以考虑一下

process this@(Sentence string _) = ...
Run Code Online (Sandbox Code Playgroud)

大致相当于

process this = let (Sentence string _) = this
               in ...
Run Code Online (Sandbox Code Playgroud)

它将@符号左侧给出的额外名称绑定到匹配的值.at模式本身匹配所有东西,但是@符号右侧的内部模式也匹配它匹配的任何东西 - 并且该模式可能不匹配所有内容,在这种情况下它只匹配Sentence构造函数.

正因为如此,该模式的版本,并与设绑定的版本具有不同的行为,如果在咱们的模式匹配结合可能会失败,所以当我们定义一个函数的多个案件在模式通常是首选,因为它允许内部模式也会影响调用函数的哪个案例.例如

safeHead xs = let (x:_) = xs in Just x
safeHead [] = Nothing
Run Code Online (Sandbox Code Playgroud)

调用时会失败[],因为xs第一个参数的模式匹配成功,所以调用该函数的第一种情况,然后xs无法匹配(x:_).但是,如果我们用as模式写这个:

safeHead xs@(x:_) = Just x
safeHead [] = Nothing
Run Code Online (Sandbox Code Playgroud)

调用with []将正常工作,因为在我们决定使用函数的第一种情况之前也检查内部模式,因此虽然xs匹配[],但(x:_)也匹配[],失败,因此第二种情况被调用.我意识到这是一个非常愚蠢的例子,特别是因为我们第二次不使用xs,但我希望它能说明差异.

  • 请注意,传统上这被称为"as-pattern",但有些人称之为"at-pattern"的想法并不令人惊讶. (2认同)
  • @Imray不是真的没有 - 我所说的是as模式允许你将名称绑定到一个值,并且还模式匹配该值.就绑定的名称而言,这类似于仅匹配名称的模式,然后让或匹配模式.但是,如果任何部分(特别是`@`右边的部分不匹配),整个模式`this @(Sentence string _)`将无法匹配(并且使用不同的情况).这与绑定名称`this`然后分别匹配`(Sentence string _)`不同. (2认同)