这是我分配给调试的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,但我希望它能说明差异.