代码之家  ›  专栏  ›  技术社区  ›  Pradeep

当模式匹配时,括号在(x:xs)中表示什么?

  •  25
  • Pradeep  · 技术社区  · 16 年前

    当使用x:xs语法拆分列表时,为什么要用括号括起来?括号的意义是什么?为什么不[x:xs]或只是x:xs?

    5 回复  |  直到 15 年前
        1
  •  44
  •   Norman Ramsey    16 年前

    cons单元格不必在每个上下文中都加括号,但在大多数上下文中,它是因为

    函数应用程序的绑定比任何中缀运算符都要紧密。

    用火信把它烧到你的大脑里。

    例子:

    length [] = 0
    length (x:xs) = 1 + length xs
    

    如果省略括号,编译器会认为您有一个参数 x 接着是一个位置不好的中缀操作符,它会怨声载道。另一方面,这还可以

    length l = case l of [] -> 0
                         x:xs -> 1 + length xs
    

    在这种情况下,两者都没有 X 也没有 xs 可以解释为函数应用程序的一部分,因此不需要括号。

    注意同样的好规则 函数应用程序比任何中缀运算符绑定得更紧密 是什么让我们写 length xs 在里面 1 + length xs 没有任何括号。中缀规则给予,中缀规则带走。

        2
  •  14
  •   sykora    16 年前

    你只需要使用cons操作符 : ,优先级较低。为了使事情保持正确,需要括号。

    你不使用 [x:xs] ,因为这将匹配一个列表,该列表的唯一元素是具有head的列表 x 尾部 xs .

        3
  •  3
  •   Rorick    16 年前

    我不知道确切的答案,但我想这是因为什么可以匹配的模式。只能匹配构造函数。构造器可以是单个词或复合词。看看下面的代码:

    data Foo = Bar | Baz Int
    
    f :: Foo -> Int
    f Bar     = 1
    f (Baz x) = x - 1
    

    单字构造器按原样匹配。但是为了避免歧义,复合构造函数必须被parens包围。如果我们跳过parens,它看起来像是与两个 独立的 争论:

    f Baz x = x - 1
    

    所以,作为 (:) 是复合的,必须是parens。跳过的parens Bar 是一种句法糖。

    更新:我意识到(正如sykora所指出的)这是操作员优先级的结果。它澄清了我的假设。函数应用程序(即函数和参数之间的空间)具有最高优先级。其他包括(:)的优先级较低。所以 f x:xs 被解释为 ((:) (f x)) xs 这大概不是我们需要的。同时 f (x:xs) 被解释为 f 应用于 x:xs 反过来呢 (:) 应用于 x 和 xs .

        4
  •  2
  •   yatima2975    16 年前

    这与解析有关。

    记住,冒号:只是一个用运算符语法编写的构造函数。所以一个函数

    foo [] = 0
    foo (x:xs) = x + foo xs
    

    也可以写为

    foo [] = 0
    foo ((:) x xs) = x + foo xs
    

    如果把括号放在最后一行,就很难解析了!

        5
  •  1
  •   C. A. McCann Ravikant Cherukuri    16 年前

    : 是一个数据构造函数,与任何其他模式匹配,但写入了中缀。括号纯粹是因为中缀优先权;它们实际上不是必需的,并且可以在优先规则允许时安全地省略。例如:

    > let (_, a:_) = (1, [2, 3, 4]) in a
    2
    > let a:_ = "xyzzy"
    'x'
    > case [1, 2, 3] of; a:b -> a; otherwise -> 0;
    1
    

    有趣的是,在一个lambda的头部,这似乎不起作用。不知道为什么。

    像往常一样,“并置”运算符比其他任何运算符绑定得更紧密,因此通常需要分隔符,但实际上它们不是 部分 模式匹配——否则您将无法使用 (x:y:zs) 而不是 (x:(y:zs)) .