为什么在没有括号的情况下,haskell中的负数不可能相乘

为什么在没有括号的情况下,haskell中的负数不可能相乘,haskell,syntax,Haskell,Syntax,在haskell gchi中乘以5*-3会给出错误和错误。但是相乘5*(-3)可以正常工作。为什么需要括号 $ ghci GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linki

在haskell gchi中乘以
5*-3
会给出错误和错误。但是相乘
5*(-3)
可以正常工作。为什么需要括号

$ ghci
GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> 5 * -3

<interactive>:2:1:
    Precedence parsing error
        cannot mix `*' [infixl 7] and prefix `-' [infixl 6] in the same infix expression
Prelude> 5 * (-3)
-15
Prelude>
$ghci
GHCi,7.4.1版:http://www.haskell.org/ghc/  :? 求救
正在加载程序包ghc prim。。。链接。。。完成。
正在加载包整型gmp。。。链接。。。完成。
正在加载包库。。。链接。。。完成。
序曲>5*-3
:2:1:
优先解析错误
不能在同一中缀表达式中混合使用“*”[infixl 7]和前缀“-”[infixl 6]
序曲>5*(-3)
-15
序曲>
因为在Haskell中如何指定运算符。不幸的是,这有点神奇。这是语言规范中的一个奇怪的角落

一元减号是语言中唯一的一元运算符。对一元减号语法的支持只是为了支持
negate
函数的语法糖

一方面,这使我们可以使
-7
-7
相同。另一方面,它破坏了其他东西,比如节语法

正如您所看到的,在编写混合固定表达式时,这会造成混乱

您需要将否定的用法括起来,如下所示:

5 * (-3)

因为-3不像其他语言那样是负数。
它是一元函数,后跟Num 3。

规则是不能在二元运算符附近使用
-
运算符(Haskell唯一的一元运算符)

因为可以在Haskell中定义新的运算符,所以使用此规则的原因是,否则可能会引入潜在的解析歧义。假设您没有使用任何空格,并且指定了
5*-3


这是否意味着
5*-3
5*-3

其他答案告诉你
-
在Haskell中是一个非常特殊的运算符,具有奇怪的语法行为。我不认为这真的回答了你的问题,因为没有任何东西可以阻止语言设计师让
5*-3
按照你期望的方式工作,即使有其他奇怪之处

因此,真正的答案是,他们根本不允许这样做


至于原因,我的猜测是因为它们的灵感不是来自类C语言的语法(如果你看Haskell语法的其余部分,确实很明显),而是来自更接近数学约定的符号,在数学中,通常需要在该位置插入一个
-3
。虽然这有点像是一个copout,因为数学通常也不使用任何东西来代替
*

但经验法则是,当括号前面有函数应用程序或更高优先级的运算符时,将负数放在括号之间。到目前为止,这个问题对我一直有效。

因为还没有公认的答案,我对这个有趣的问题做了一些研究,因为我发现在另一个地方也没有答案

简短的回答是:语法不允许这样做。

让我再解释一点数据,但首先让我们记住:

在haskell上,运算符是

现在,让我们看看错误消息:

Precedence parsing error
    cannot mix `*' [infixl 7] and prefix `-' [infixl 6] in the same infix expression
这意味着什么?那么,我们应该开始定义什么是
infixl7
infixl6
。在他们的语法上,他们有这样的东西:

infixr 9 .
infixr 8 ^, ^^, **
infixl 7 *, /, `quot`, `rem`, `div`, `mod`
infixl 6 +, -
infixr 5 :
infix 4 ==, /=, <, <=, >=, >
infixr 3 &&
infixr 2 ||
infixl 1 >>, >>=
infixr 1 =<<
infixr 0 $, $!, `seq`
Prelude> 5 * +3
您将得到以下错误:

parse error on input `+'
等等,如果这是sintax错误,为什么错误消息不同

好的,
一元“-”运算符在haskell中似乎非常特殊(正如其他答案所说),并且被用于语法的其他部分,因此,理论上这将转到语法树的另一个分支,并在其他地方抛出错误


如果您想了解更多有关
一元“-”运算符的信息,可以。

这是一个合理的猜测,但实际上并非如此。您可以对优先级低于加法和减法的运算符使用
-
5==-3
正常工作。但它确实需要间隔,就像所有连接为有效词汇标记的标记一样。只是Haskell(可能是出于设计)有相对较少的两个类似运算符的令牌自然顺序排列的情况,但也可能发生,例如另一个例子是
->
\
中的
\x->\y->x+y
。实际上,
是一个二进制运算符,而不是一元运算符。一元否定函数被称为
否定
(因为在其他答案中讨论了歧义)<代码>-3
是Haskell中的数字文字,而不是函数调用。