Haskell 模式匹配时,(x:xs)中的括号表示什么?
当您使用x:xs语法拆分列表时,为什么要将其包装在括号中?括号的意义是什么?为什么不使用[x:xs]或仅使用x:xs?您只是在使用cons运算符Haskell 模式匹配时,(x:xs)中的括号表示什么?,haskell,syntax,Haskell,Syntax,当您使用x:xs语法拆分列表时,为什么要将其包装在括号中?括号的意义是什么?为什么不使用[x:xs]或仅使用x:xs?您只是在使用cons运算符:,它的优先级较低。括号是必要的,这样事情就不会出错 你不用[x:xs],因为这会匹配一个列表,它的唯一元素是一个头x尾xs的列表,我不知道确切的答案,但我想这是因为可以在模式中匹配什么。只能匹配构造函数。构造函数可以是单个单词或复合词。看看下面的代码: data Foo = Bar | Baz Int f :: Foo -> Int f Bar
:
,它的优先级较低。括号是必要的,这样事情就不会出错
你不用
[x:xs]
,因为这会匹配一个列表,它的唯一元素是一个头x
尾xs
的列表,我不知道确切的答案,但我想这是因为可以在模式中匹配什么。只能匹配构造函数。构造函数可以是单个单词或复合词。看看下面的代码:
data Foo = Bar | Baz Int
f :: Foo -> Int
f Bar = 1
f (Baz x) = x - 1
单字构造函数按原样匹配。但是复合构造函数必须被paren包围,以避免歧义。如果我们跳过parens,它看起来像是针对两个独立参数进行匹配:
f Baz x = x - 1
因此,由于(:)
是复合的,所以它必须在parens中。跳过Bar
的paren是一种语法糖分
更新:我意识到(正如sykora所指出的)这是运算符优先级的结果。它澄清了我的假设。函数应用程序(函数和参数之间的空格)具有最高优先级。其他包括(:)的优先级较低。所以
fx:xs
被解释为((:)(fx))xs
,这大概不是我们需要的。而f(x:xs)
被解释为f
应用于x:xs
,这又是(:)
应用于x
和xs
,这与解析有关
记住,冒号:只是一个用运算符语法编写的构造函数。那么一个函数
foo [] = 0
foo (x:xs) = x + foo xs
也可以写成
foo [] = 0
foo ((:) x xs) = x + foo xs
如果将括号放在最后一行中,将很难解析
:
是一个数据构造函数,与任何其他模式匹配一样,但都是用中缀编写的。括号的存在纯粹是因为中缀优先;它们实际上不是必需的,并且可以在优先规则允许的情况下安全地省略。例如:
> 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))
cons单元格不必在所有上下文中都加括号,但在大多数上下文中,这是因为
函数应用程序绑定比任何中缀运算符都要紧密。
用火书的形式把它烧进你的大脑
例如:
length [] = 0
length (x:xs) = 1 + length xs
如果省略括号,编译器会认为您的参数x
后面跟了一个位置不正确的中缀运算符,它会发出痛苦的抱怨。另一方面,这是可以的
length l = case l of [] -> 0
x:xs -> 1 + length xs
在这种情况下,x
和xs
都不可能被解释为函数应用程序的一部分,因此不需要括号
请注意,相同的奇妙规则函数应用程序绑定比任何中缀运算符都要紧密,它允许我们在
1+length xs
中写入length xs
,而无需任何括号。中缀规则给出,中缀规则带走。您有没有一个例子说明它在()中的包装位置?x:xs可以按原样用于描述具有列表的第一个元素的列表。[x:xs]将是一个包含列表x:xs的列表。他说的是模式匹配,而不是构建列表。我从未尝试过那种特定的[x:xs]
模式,但你当然是对的;它与顶层的单例列表相匹配。该模式的脱模符号为:((x:xs):[])
+1表示火灾字母。在我内化了这个规则之后,我的Haskell代码就不再像Lisp了。