2

我正在尝试xor通过以下方式在 Haskell 中定义使用模式匹配:

(xor) :: Bool -> Bool -> Bool
True    xor False   = True
False   xor True    = True
True    xor True    = False
False   xor False   = False

然而,这给出了错误:

Invalid type signature: (xor) :: Bool -> Bool -> Bool
Should be of form <variable> :: <type>

我很困惑为什么会抛出这个错误。另外,如果我用脚本加载之xor类的东西替换的话。&&

4

2 回答 2

15

只有运算符应该被括在类型签名的括号中,例如

(&&) :: Bool -> Bool -> Bool

普通函数应不写,

xor :: Bool -> Bool -> Bool

在定义方程式中,您必须将其括在反引号中,

True `xor` True = False

如果您想使用中缀表示法定义它。没有反引号,您可以使用前缀符号定义它,

xor True False = True

但是请注意,

  • xorBits类中的一个函数,因此使用它Bool可能会出乎意料
  • xor ≡ (/=)
于 2013-02-12T16:27:36.293 回答
9

Haskell 区分标识符运算符符号。标识符是字母数字加号',它们本身就是有效的术语;如果标识符prefix具有函数类型,则可以将其称为prefix arg1 arg2. 运算符名称是符号序列,称为arg1 !&$ arg2. 1 但有时,您希望将标识符用作中缀运算符或将中缀运算符视为标识符。因此,如果你用`s 包围任何前缀函数名,它就会成为一个运算符,你可以(必须)将它用作中缀:arg1 `prefixFunc` arg2。相反,如果你把一个中缀运算符的名字用括号括起来,它本身就在语法上是有效的,所以可以用前缀的形式来调用:(!&$) arg1 arg2. 2

在为变量声明类型签名时,您需要将变量的名称作为标识符3 对于一个普通的函数名,比如xor,那只是名字;对于像 . 这样的运算符&&,您将其包裹在括号中,如上所述,这就是您编写(&&) :: Bool -> Bool -> Bool. 因此,你会写

xor :: Bool -> Bool -> Bool
True  `xor` False = True
False `xor` True  = True
True  `xor` True  = False
False `xor` False = False

请注意,我必须进行两项更改。如果您在定义行中省略了反引号,就好像您在尝试进行模式匹配:True看起来像一个带有两个参数的构造函数,并且xor是第一个参数。4

(另外,只是为了踢球,一个更短的定义:xor = (/=):-))


Haskell 2010 报告中的引用:

1词法结构在§2.4

2表达式结构在§3.2中。

3类型签名的结构见§4.4.1,参考§3.2中var定义。

4绑定的结构在§4.4.3中。

于 2013-02-12T16:49:20.587 回答