ПРИМЕЧАНИЕ. Несмотря на то что переменные типа могут иметь имена, состоящие более чем из одной буквы, мы обычно называем их a, b, c, d…
Помните функцию fst
? Она возвращает первый компонент в паре. Проверим её тип:
ghci> :t fst
fst :: (a, b) –> a
Можно заметить, что функция fst
принимает в качестве параметра кортеж, который состоит из двух компонентов, и возвращает значение того же типа, что и первый компонент пары. Поэтому мы можем применить функцию fst
к паре, которая содержит значения любых двух типов.
Заметьте, что хотя a
и b
– различные переменные типа, они вовсе не обязаны быть fst
лишь означает, что тип первого компонента и тип возвращаемого значения одинаковы.
Классы типов
Хорошим примером будет класс типов, определяющий равенство. Значения многих типов можно сравнивать на равенство с помощью оператора ==
. Посмотрим на его сигнатуру:
ghci> :t (==)
(==) :: (Eq a) => a –> a –> Bool
Заметьте: оператор равенства ==
– это функция. Функциями также являются операторы +
, *
, –
, /
и почти все остальные операторы. Если имя функции содержит только специальные символы, по умолчанию подразумевается, что это инфиксная функция. Если мы захотим проверить её тип, передать её другой функции или вызвать как префиксную функцию, мы должны поместить её в круглые скобки.
Интересно… мы видим здесь что-то новое, а именно символ =>
. Всё, что находится перед символом =>
, называется Bool
. Тип этих двух значений должен быть экземпляром класса Eq
» (это и есть ограничение класса).
Класс типа Eq
предоставляет интерфейс для проверки на равенство. Каждый тип, для значений которого операция проверки на равенство имеет смысл, должен быть экземпляром класса Eq
. Все стандартные типы языка Haskell (кроме типов для ввода-вывода и функций) являются экземплярами Eq
.
ПРИМЕЧАНИЕ. Важно отметить, что классы типов в языке Haskell не являются тем же самым, что и классы в объектно-ориентированных языках программирования.
У функции elem
тип (Eq a) => a –> [a] –> Bool
, потому что она применяет оператор ==
к элементам списка, чтобы проверить, есть ли в этом списке значение, которое мы ищем.
Далее приводятся описания нескольких базовых классов типов.
Класс Eq
Класс Eq
используется для типов, которые поддерживают проверку равенства. Типы, являющиеся его экземплярами, должны реализовывать функции ==
и /=
. Так что если у нас есть ограничение класса Eq
для переменной типа в функции, то она может использовать ==
или /=
внутри своего определения. Все типы, которые мы упоминали выше, за исключением функций, входят в класс Eq
, и, следовательно, могут быть проверены на равенство.
ghci> 5 == 5
True
ghci> 5 /= 5
False
ghci> 'a' == 'a'
True
ghci> "Хо Хо" == "Хо Хо"
True
ghci> 3.432 == 3.432
True
Класс Ord
Класс Ord
предназначен для типов, которые поддерживают отношение порядка.
ghci> :t (>)
(>) :: (Ord a) => a –> a –> Bool
Все типы, упоминавшиеся ранее, за исключением функций, имеют экземпляры класса Ord
. Класс Ord
содержит все стандартные функции сравнения, такие как >
, <
, >=
и <=
. Функция compare
принимает два значения одного и того же типа, являющегося экземпляром класса Ord
, и возвращает значение типа Ordering
. Тип Ordering
может принимать значения GT
, LT
или EQ
, означая, соответственно, «больше чем», «меньше чем» и «равно».
ghci> "Абракадабра" < "Зебра"
True
ghci> "Абракадабра" `compare` "Зебра"
LT
ghci> 5 >= 2
True
ghci> 5 `compare` 3
GT
Класс Show