考虑运行命令的以下函数:
getGrepStdout :: IO String
getGrepStdOut = do let cmd' = "grep"
pattern' = "//"
options' = "-nR"
path' = "/path/to/file"
stdin' = ""
args' = [pattern', options', path']
(_, stdout', _) <- readProcessWithExitCode cmd' args' stdin'
return stdout'
注意第二行到最后一行有一个双_
通配符匹配(在do
块内)。在我的情况下,这似乎编译得很好,但我想知道它是否正式出现问题?
答案 0 :(得分:4)
不,在模式匹配中,在do-blocks或其他方面有一个或多个_
没有问题。为什么你认为可能存在?
答案 1 :(得分:2)
你应该没事(至少GHC)。
担心会很高兴,因为如果你要使用任何其他标识符,这会爆发!
Prelude> :{
Prelude| do
Prelude| (x,x) <- return (1,1)
Prelude| return x
Prelude| :}
<interactive>:12:6:
Conflicting definitions for ‘x’
Bound at: <interactive>:12:6
<interactive>:12:8
In a pattern binding in
'do' block
最重要的是,这让人感到害怕:
return (1,1) >>= \(x,x) -> return x
并且lambda抽象不允许您使用相同的本地名称两次。 _
获得特殊待遇。
因此,对于_
,您告诉编译器您不需要任何值。并且不要对价值做任何假设。
一般情况下,你不应该担心在同一范围内对你的定义进行抨击,Haskell不会真的让你这么做。 Here's关于无法执行以下操作的相关问题:
plus a a = 2*a
plus a b = a + b
这实际上非常类似于这种情况。 _
需要特殊待遇。
答案 2 :(得分:1)
严格地说,_
实际上不再是x
或arg
的通配符模式。然而,它是一个洞。这意味着它不仅可以接受任何值,而且不会将该值绑定到任何特定变量。由于_
根本不绑定值,因此在相同的函数声明中使用它两次在理论上和实际上都是完全有效的。