Search code examples
haskellpattern-matchingtype-signature

Haskell: Pattern matching, Identifiers and operators


I'm trying to define xor using pattern matching in Haskell by:

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

However this gives the error:

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

I'm confused as to why this error is being thrown. Also if I replace xor with something such as && the script loads fine.


Solution

  • Haskell differentiates between identifiers and operator symbols. Identifiers are alphanumeric plus ', and are valid terms on their own; if an identifier prefix has a function type, you can thus call it as prefix arg1 arg2. Operator names are sequences of symbols, and are called as arg1 !&$ arg2.1 But sometimes, you want to use identifiers as infix operators or treat an infix operator as an identifier. Thus, if you surround any prefix function name with `s, it becomes an operator and you can (must) use it as infix: arg1 `prefixFunc` arg2. And contrariwise, if you wrap an infix operator name in parentheses, it becomes syntactically valid on its own, and so can be called in prefix form: (!&$) arg1 arg2.2

    When declaring a type signature for a variable, you need to give the variable's name as an identifier.3 For an ordinary function name like xor, that's just the name; for an operator like &&, you wrap it in parentheses, as discussed above, which is why you write (&&) :: Bool -> Bool -> Bool. Thus, you'd write

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

    Note that I had to make two changes. If you left off the backticks in the definition lines, it'll be as though you were trying to do pattern matching: True would look like a constructor which took two arguments, and xor would be the first one.4

    (Also, just for kicks, a shorter definition: xor = (/=) :-))


    Citations in the Haskell 2010 report:

    1 The lexical structure is in §2.4

    2 The expression structure is in §3.2.

    3 The structure of type signatures is in §4.4.1, referring to the definition of var in §3.2.

    4 The structure of bindings is in §4.4.3.