这是我分配给调试的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)
| ...
| ...
| ...
| ...
我不理解或不认识的这个程序的唯一部分是行process this@(Sentence string _) = do
我以前从未见过this@
而我也不太确定(Sentence string _)
中的下划线是什么意思。
答案 0 :(得分:7)
this@
是'as-pattern'的示例,而_
是通配符模式的示例。当我们不关心模式中该点的值时使用外卡模式,因此模式中的_
将与任何内容匹配,并且它不绑定任何本地名称/变量。< / p>
另一方面,当我们想要绑定一个额外的本地名称/变量同时也匹配它时,我们使用as模式。你可以考虑那个
process this@(Sentence string _) = ...
大致相当于
process this = let (Sentence string _) = this
in ...
它将@
符号左侧给出的额外名称绑定到匹配的值。 at模式本身匹配所有内容,但@
符号右侧的内部模式也匹配它匹配的任何内容 - 并且该模式可能不匹配所有内容,在这种情况下它只匹配一个{ {1}}构造函数。
因此,如果let绑定中的模式匹配失败,则at模式版本和let绑定的版本具有不同的行为,因此当我们为函数定义多个case时,at模式通常是首选的,如它允许内部模式也影响调用函数的哪个案例。例如
Sentence
使用safeHead xs = let (x:_) = xs in Just x
safeHead [] = Nothing
调用时会失败,因为第一个参数的[]
模式匹配成功,因此调用该函数的第一个案例,然后xs
无法匹配反对xs
。但是,如果我们用as模式写这个:
(x:_)
使用safeHead xs@(x:_) = Just x
safeHead [] = Nothing
调用可以正常工作,因为在我们决定使用函数的第一个案例之前也会检查内部模式,因此虽然[]
与xs
匹配,但{ {1}}也与[]
匹配,失败,因此第二种情况被调用。我意识到这是一个非常愚蠢的例子,特别是因为我们第二次不使用xs,但我希望它能说明差异。
答案 1 :(得分:4)
@
定义as pattern,允许您为匹配的内容命名。在这种情况下,this
是您要匹配的Sentence
值的名称。
答案 2 :(得分:4)
Sentence
是一个带String
和Task
的构造函数,在模式this@(Sentence string _)
中,this
是as pattern的名字整句,string
命名为句子String
,下划线指的是Task
以其他方式命名的地方,基本上说Task
应该在那里被忽略。