Haskell: сопоставление с образцом, идентификаторы и операторы

Я пытаюсь определить 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 чем-то вроде &&, скрипт загрузится нормально.


person BradStevenson    schedule 12.02.2013    source источник


Ответы (2)


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, ссылаясь на определение var в §3.2.

4 Структура привязок описана в §4.4.3.

person Antal Spector-Zabusky    schedule 12.02.2013

Только операторы должны быть заключены в круглые скобки для подписи типа, например

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

обычные функции должны быть написаны без,

xor :: Bool -> Bool -> Bool

и в определяющих уравнениях вы должны заключить его в обратные кавычки,

True `xor` True = False

если вы хотите определить его с помощью инфиксной нотации. Без обратных кавычек вы можете определить его, используя префиксную нотацию,

xor True False = True

Обратите внимание, однако,

  • xor — это функция из класса Bits, поэтому ее использование для Bool может оказаться неожиданным.
  • xor ≡ (/=)
person Daniel Fischer    schedule 12.02.2013