Haskell:模式匹配,标识符和运算符

时间:2013-02-12 16:25:05

标签: haskell pattern-matching type-signature

我正在尝试使用Haskell中的模式匹配来定义xor

(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之类的内容替换&&,则脚本加载正常。

2 个答案:

答案 0 :(得分:15)

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

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

普通函数应在没有的情况下编写,

xor :: Bool -> Bool -> Bool

并且在定义的等式中,你必须将它括在反引号中,

True `xor` True = False

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

来定义它
xor True False = True

但请注意

  • xor是来自Bits类的函数,因此将其用于Bool可能会出乎意料
  • xor ≡ (/=)

答案 1 :(得分:8)

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

在声明变量的类型签名时,您需要将变量的名称​​作为标识符 3 对于像{{这样的普通函数名称1}},这只是名字;对于像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将是第一个。 4

(另外,只是为了踢,更短的定义:xor: - ))


the Haskell 2010 report中的引文:

1 词汇结构位于§2.4

2 表达式结构位于§3.2

3 类型签名的结构位于§4.4.1,指的是§3.2 var 的定义。

4 绑定的结构在§4.4.3