【问题标题】:Double wildcarding within a do block in HaskellHaskell中do块内的双重通配符
【发布时间】:2016-05-14 00:49:01
【问题描述】:

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

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

【问题讨论】:

  • 一种思考方式:如果您永远不需要提及他们,那么您是否有两个名为 Darryl 的兄弟也没关系。

标签: haskell wildcard


【解决方案1】:

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

【讨论】:

  • 关于为什么它可能是一个问题的假设。例如在 python 中_ 不是通配符,只是一个常规变量名,非正式地用于指示通配符。
  • 好吧,您可以在 &lt;- 的左侧进行一些简单的模式匹配(例如 Just val &lt;- someMaybeOperation),因此可以假设您正在对 _ 进行统一(例如,什么如果你有Pair x x &lt;- operationGivingPair?)
【解决方案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

这实际上与这种情况非常相似。需要_的特殊处理。

【讨论】:

  • _ 不是标识符。如果它是 f _ = _ 会编译,而它不会。这是一个通配符。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2020-05-03
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    相关资源
    最近更新 更多