Главная » Haskell » Автоматическое построение экземпляров

0

В языке Haskell имеется возможность автоматического построения экземпляров классов для некоторых классов из стандартного модуля Prelude. У разработчика программного обеспечения в таком случае нет необходимости явно определять экземпляры. Для этих целей используется ключевое слово deriving, которое записывается после  объявления алгебраического  типа данных или изоморфного типа. После этого ключевого слова идёт перечисление классов, для которых необходимо автоматически  построить экземпляры. Данное перечисление заключается в круглые скобки, если классов  несколько. Если класс один, то можно просто привести его наименование. Например:

newtype MyBool =  MB  Bool deriving Show

data  Number

= N  Integer

| F Float

deriving (Eq,  Ord,  Show, Read)

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

Классами из стандартного модуля Prelude, для которых можно автоматически строить экземпляры, являются: Eq, Ord, Enum, Bounded, Show и Read. Впрочем, для некоторых классов, которые  определены в  стандартных библиотеках, тоже  можно использовать методику  автоматического построения экземпляров. Обычно такие классы достаточно просты, чтобы транслятор языка Haskell мог самостоятельно понять, как строить экземпляр для них. Например, для класса Ix можно автоматически построить экземпляры.

Тела методов классов, для которых автоматически строятся экземпляры, создаются транслятором языка Haskell при помощи применения несложных синтаксических правил, работающих с определениями класса и типа, которые связываются экземпляром. Пусть имеется некоторый тип T, объявленный следующим образом (для определённости и простоты рассмотрения пусть это будет алгебраический тип данных; для изоморфных типов рассуждения и правила такие же):

data cx => T a1 . . . ak = K1 t11 . . . t1k1

| . . .

| Kn  tn1 . . . tnkn

deriving (C1, . . . , Cm)

Тогда автоматическое объявление экземпляра для класса  C возможно при выполнении следующих условий:

1)                        Класс C является одним из классов Eq, Ord, Enum, Bounded,  Show или Read.

2)                        Существует контекст cxr такой, что cxr => C tij  выполняется для всех компонентов типа tij .

3)                        Если класс C  является классом Bounded,  то тип T должен  представлять собой либо перечисление (все его конструкторы не принимают на вход аргументов), либо иметь только один конструктор.

4)                        Если класс C является классом Enum, то тип T должен безусловно представлять собой перечисление.

5)                        Не должно существовать никакого явного определения экземпляра класса C

для типа T.

Определения изоморфных типов  при  помощи ключевого слова  newtype в этом случае просто трактуется как объявление алгебраического типа данных с одним конструктором.

Каждое автоматически создаваемое определение экземпляра  по описываемой технологии в данном случае будет иметь вид:

instance (cx, cxr) => Ci (T a1 . . . ak ) where  { d }

где d строится автоматически в зависимости от методов класса Ci  и определения T. При этом контекст cxr  является самым узким контекстом, который удовлетворяет пункту 2 перечисленных выше принципов. Для взаимно рекурсивных типов данных транслятору языка Haskell может потребоваться произвести много дополнительных вычислений для его получения.

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

Источник: Душкин Р. В., Справочник по языку Haskell. М.: ДМК Пресс, 2008. 544 с., ил.

По теме:

  • Комментарии