ТОП 10:

Классы типов, второй семестр



Мы уже изучили несколько стандартных классов типов языка Has- kell и некоторые типы, имеющие для них экземпляры. Также мы знаем, как автоматически сделать для наших типов экземпляры стандартных классов, стоит только попросить Haskell автомати- чески сгенерировать нужное нам поведение. В этой главе будет рассказано о том, как писать свои собственные классы типов и как создавать экземпляры класса вручную.

Вспомним, что классы типов по сути своей подобны интерфей- сам. Они определяют некоторое поведение (проверку на равенс- тво, проверку на «больше-меньше», перечисление элементов). Типы, обладающие таким поведением, можно сделать экземпля- ром класса типов. Поведение класса типов определяется функция- ми, входящими в класс, или просто декларацией класса; элементы класса мы потом должны будем реализовать. Таким образом, если мы говорим, что для типа имеется экземпляр класса, то подразуме- ваем, что можем использовать все функции, определённые в классе типов в нашем типе.

ПРИМЕЧАНИЕ.Классы типов практически не имеют ничего об- щего с классами в таких языках, как Java или Python. Это сбивает с толку, поэтому советую вам забыть всё, что вы знаете о классах в императивных языках!

«Внутренности» класса Eq

Возьмём для примера класс типов Eq: он используется в отношении неких значений, которые можно проверить на равенство. Он опреде- ляет операторы == и /=. Если у нас есть тип, скажем, Car (автомобиль),


 

и сравнение двух автомобилей с помощью функции == имеет смысл, то имеет смысл и определить для типа Car экземпляр класса Eq.

 
 

Вот как класс Eq определён в стандартном модуле:

class Eq a where

(==) :: a –> a –> Bool

 
 

(/=) :: a –> a –> Bool x == y = not (x /= y) x /= y = not (x == y)

О-хо-хо!.. Новый синтаксис и новые ключевые слова. Не беспо- койтесь, скоро мы это поясним. Прежде всего, мы записали деклара- цию class Eq a where – это означает, что мы определяем новый класс, имя которого Eq. Идентификатор а – это переменная типа; иными словами, идентификатор играет роль типа, который в дальнейшем будет экземпляром нашего класса. Эту переменную необязательно называть именно а; пусть даже имя не состоит из одной буквы, но оно непременно должно начинаться с символа в нижнем регистре. Затем мы определяем несколько функций. Нет необходимости пи- сать реализацию функций – достаточно только декларации типа.

Некоторым будет проще понять эту декларацию, если мы запи- шем class Eq equatable where, а затем декларации функций, напри- мер (==) :: equatable –> equatable –> Bool.

Мы определили тела функций для функций в классе Eq, притом определили их взаимно рекурсивно. Мы записали, что два экземпляра класса Eq равны, если они не отличаются, и что они отличаются, если не равны. Необязательно было поступать так, и всё же скоро мы увидим, чем это может быть полезно.

Если записать декларацию class Eq a where, описать в ней функ- цию таким образом: (==) :: a -> a -> Bool, а затем посмотреть объявле- ние этой функции, мы увидим следующий тип: (Eq a) => a –> a –> Bool.

 







Последнее изменение этой страницы: 2017-02-17; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.232.38.214 (0.005 с.)