Россия, Петерубрг, СПБ-ГПУ, 1998 |
Объявления и связывания имен
Перевод:
Объявления в синтаксической категории topdecls (список-объявлений-верхнего-уровня) допустимы только на верхнем уровне модуля Haskell (см. лекцию "Модули" ), тогда как decls (список-объявлений) можно использовать или на верхнем уровне, или во вложенных областях видимости (т.е. в пределах конструкций let или where ).
Для описания мы разделили объявления на три группы: группу определяемых пользователем типов данных, состоящую из объявлений type, newtype и data (раздел "Объявления и связывания имен" ), группу классов типов и перегрузок операторов, состоящую из объявлений class, instance и default (раздел "Объявления и связывания имен" ), и группу вложенных объявлений, состоящую из связываний значений, сигнатур типов и infix-объявлений (раздел "Объявления и связывания имен" ).
В Haskell есть несколько примитивных типов данных, которые являются "зашитыми" (такие как целые числа и числа с плавающей точкой), но большинство "встроенных" типов данных определено с помощью обычного кода на Haskell с использованием обычных объявлений type и data. Эти "встроенные" типы данных подробно описаны в разделе "Предопределенные типы и классы" .
4.1 Обзор типов и классов
Haskell использует традиционную систему полиморфных типов Хиндли-Милнера (Hindley-Milner) для того, чтобы обеспечить статическую семантику типов [3, 5], но система типов была расширена с помощью классов типов (или просто классов), которые обеспечивают структурированный способ ввести перегруженные функции.
Объявление class (раздел "Объявления и связывания имен" ) вводит новый класс типа и перегруженные операции, которые должны поддерживаться любым типом, который является экземпляром этого класса. Объявление instance (раздел "Объявления и связывания имен" ) объявляет, что тип является экземпляром класса и включает определения перегруженных операций, называемых методами класса, инстанцированных на названном типе.
Например, предположим, что мы хотим перегрузить операции (+) и negate на типах Int и Float. Мы вводим новый класс типов, названный Num:
class Num a where - упрощенное объявление класса Num (+) :: a -> a -> a - (Класс Num определен в Prelude) negate :: a -> a
Это объявление можно толковать так: "тип a является экземпляром класса Num, если есть методы класса (+) и negate заданных типов, определенные на этом типе."
Затем мы можем объявить Int и Float экземплярами этого класса:
instance Num Int where - упрощенный экземпляр Num Int x + y = addInt x y negate x = negateInt x instance Num Float where - упрощенный экземпляр Num Float x + y = addFloat x y negate x = negateFloat x
где предполагается, что addInt, negateInt, addFloat и negateFloat - примитивные, в данном случае, функции, но вообще могут быть любыми определяемыми пользователем функциями. Первое сверху объявление можно толковать так: " Int является экземпляром класса Num в соответствии с этими определениями (т.е. методами класса) для (+) и negate."
Большее количество примеров классов типов можно найти в работах Джонса (Jones) [7] или Уодлера и Блотта (Wadler и Blott) [12]. Термин "класс типа" использовался для описания системы типов в исходном языке Haskell 1.0, а термин "конструктор класса" - для описания расширения исходных классов типов. Больше нет никакой причины использовать два различных термина: в этом описании "класс типа" включает и классы типов исходного языка Haskell , и конструируемые классы, введенные Джонсом (Jones).