Haskell 中 do 块中的双重通配符

Double wildcarding within a do block in Haskell

考虑以下运行命令的函数:

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 块内)。这在我的情况下似乎编译得很好,但我想知道从形式上讲这是否有问题?

不,在模式匹配、do 块或其他方面有一个或多个 _ 没有问题。为什么你认为可能会有?

严格来说,_ 并不比 xarg 更像是一种通配符模式。然而,它是一个洞。这意味着它不仅可以接受任何值,而且不会将该值绑定到任何特定变量。由于 _ 根本不绑定值,因此在同一个函数声明中使用它两次是完全有效的,无论是理论上还是实用上。

你应该没问题(至少使用 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

其实和这种情况很相似。 _需要特殊对待