data Type = Name1
Sub11
Sub12
...
Sub1N
| Name2
Sub21
Sub22
...
Sub2M
...
| NameK
SubK1
SubK2
...
SubKP
Такие типы называют алгебраическими типами данных . С помощью типов мы определяем основные поня-
тия и способы их комбинирования.
Значения
Как это ни странно, нам встретилась лишь одна операция создания значений: определение синонима . Она
пишется так
name x1
x2 ...xN = Expr1
name x1
x2 ...xN = Expr2
name x1
x2 ...xN = Expr3
Слева от знака равно стоит составное имя, а справа от знака равно некоторое выражение, построенное
согласно типам. Разные комбинации имени name с параметрами определяют разные уравнения для синонима
name.
Также мы видели символ _, который означает “всё, что угодно” на месте аргумента. А также мы увидели,
как с помощью переменных можно перетаскивать значения из аргументов в результат.
Ядро Haskell | 21
Классы типов
Нам встретилась одна конструкция определения классов типов:
class Namea where
method1 ::a -> ...
method2 ::a -> ...
...
methodN ::a -> ...
Экземпляры классов типов
Нам встретилась одна конструкция определения экземпляров классов типов:
instance Name Type where
method1 x1 ...xN = ...
method2 x1 ...xM = ...
...
methodN x1 ...xP = ...
Типы, значения и классы типов
Каждое значение имеет тип. Значение v имеет тип Tна Haskell:
v :: T
Функциональный тип обозначается стрелкой: a ->b
fun ::a ->b
Тип значения может иметь контекст, он говорит о том, что параметр должен принадлежать классу типов:
fun1 :: Сa
=>a ->a
fun2 ::( C1a, C2, ..., CN) =>a ->a
Суперклассы
Также контекст может быть и у классов, запись
class Aa => Ba where
...
Означает, что класс Bцеликом содержится в A, и перед тем как объявлять экземпляр для класса B, необ-
ходимо определить экземпляр для класса A. При этом класс Aназывают суперклассом для B.
1.7 Двумерный синтаксис
Наверное вы обратили внимание на то, что в Haskell нет разделителей строк и дополнительных скобок,
которые бы указывали границы определения классов или функций. Компилятор Haskell ориентируется по
переносам строки и отступам.
Так если мы пишем в классе:
class Eqa where
( ==) ::a ->a ->a
( /=) ::a ->a ->a
По отступам за первой строкой определения компилятор понимает, что класс содержит два метода. Если
бы мы написали:
class Eqa where
( ==) ::a ->a ->a
( /=) ::a ->a ->a
22 | Глава 1: Основы
То смысл был бы совсем другим. Теперь мы определяем класс Eqс одним методом ==и указываем тип
некоторого значения ( /=). Основное правило такое: конструкции, расположенные на одном уровне, вырав-
ниваются с помощью отступов. Чем правее находится определение, тем глубже оно вложено в какую-нибудь
специальную конструкцию. Пока нам встретилось лишь несколько специальных конструкций, но дальше
появятся и другие. Часто отступы набираются с помощью табуляции. Это удобно. Но лучше пользоваться
пробелами или настроить ваш любимый текстовый редактор так, чтобы он автоматически заменял табуля-
цию на пробелы. Зачем это нужно? Дело в том, что в разных редакторах на табуляцию может быть назначено
разное количество пробелов, так код набранный с двухзначной табуляцией будет очень трудно прочитать
если открыть его в редакторе с четырьмя пробелами вместо табуляции. Поскольку очень часто табуляция
перемежается с пробелами и выравнивание может “поехать”. Поэтому признаком хорошего стиля в Haskell
считается полный отказ от табуляции.
1.8 Краткое содержание
Итак подведём итоги: у нас есть две операции для определения типов (сумма и произведение) и по одной
для значений (синонимы), классов типов и экземпляров. А также бесконечное множество их комбинаций, из
Читать дальше