- •1. Поколения языков программирования.
- •2.Понятие фп, история развития.
- •1 . Трактовка функции через понятие переменная
- •2. Определения без переменных:
- •3.Программирование при помощи функций.
- •4. Программирование при помощи процедур.
- •5. Символьные данные в строго-функциональных языках.
- •6.Элементарные селекторы, конструкторы и предикаты.
- •7. Рекурсивные функции.
- •8. Проблема выбора подфункции
- •9. Накапливающий параметр — аккумулятор
- •10. Локальное определение.
- •11. Функции высших порядков.
- •12. Фвп применительно к языку Haskell.
- •13. Основы лямбда исчисления
- •14. Правило преобразования лямбда выражения.
- •15. Ромбическое свойство системы редукций.
- •16. Стандартные порядки редукций.
- •18. Структуры данных и их типы на языке Haskell.
- •1. Синонимы типов
- •19. Понятие модуля в Haskell.
- •Абстрактные типы данных
- •Другие аспекты использования модулей
- •20. Классы и их экземпляры в Haskell.
- •21. Наследование в языке Haskell.
- •22. Сорта типов и структуры данных.
- •[Править]Определение
- •[Править]Примеры
21. Наследование в языке Haskell.
Наследование
Если один класс находится в отношении наследования с другим классом, то это обозначает, что при реализации класса-наследника экземпляром такого класса должны поддерживаться все методы базового класса (то есть по сути тип, являющийся экземпляром класса-наследника, должен быть и экземпляром базового класса).
Так, например, в стандартном модуле Prelude определен класс Ord, представляющий сравнимые типы данных. Этот класс унаследован от класса Eq, так как сравнимые типы данных также могут быть разделены на классы эквивалентности при помощи операций (==) (равно) или (/=) (не равно). Определение класса Ord выглядит следующим образом:
class (Eq a) => Ord a where
(<), (>), (<=), (>=) :: a -> a -> Bool
min, max :: a -> a -> a
Класс Ord, параметризующий тип а наследует все методы класса Eq (==), (/=), но определяет и свои собственные.
Haskell поддерживает множественное наследование (не каждый объектно-ориентированный язык программирования поддерживает такой тип наследования). В случае использования наследования от нескольких базовых классов всех их просто надо перечислить через запятую в соответствующей секции с контекстом.
Определение класса Ord, данное выше, можно прочитать так: «Класс Ord, параметризующий тип a, наследует все методы класса Eq, но при этом определяет свои собственные, а именно (перечисление методов и их типов)».
Все экземпляры класса Ord должны определять, кроме операций «меньше», «больше», «меньше или равно», «больше или равно», «минимум» и «максимум», еще и операции сравнения (==) и (/=), так как такие типы должны быть в то же самое время и экземплярами Eq. То есть экземпляры классов, унаследованных от некоторого базового класса (в том числе и нескольких), должны, естественно, поддерживать и все методы базовых классов.
На отношение наследования классов а языке Haskell накладывается одно очень важное ограничение. Цепочка отношений наследования не должна иметь транзитивных замыканий любой сложности, то есть граф таких отношений должен быть ациклическим. Класс не может быть наследником самого себя, даже опосредованно через другие классы. В противном случае произойдет ошибка трансляции.
class (Read a, Show a) => Textual a
Подобное объявление может быть полезно для объединения совокупности классов в больший класс, который унаследует все методы исходных классов.
Реализация
Класс в Haskell не является типом данных. Невозможно создать в памяти объект, чей тип был бы некоторым классом и на который распространялись бы методы обработки, определенные этим классом. Для того чтобы иметь такую возможность, необходимо определить то, какие именно типы данных являются экземплярами классов. Для этого используется ключевое слово instance.
Например, в стандартном модуле Prelude определено, что тип Int является экземпляром класса Eq, то есть значения типа Int (целые числа) могут быть сравниваемы друг с другом при помощи операций сравнения (==) и (/=). Этот факт описан следующим образом:
instance Eq Int where
(==) = primEqInt
(/=)
Данная запись может быть прочитана так: «Тип Int является экземпляром класса Eq, при этом метод (==) определяется через функцию primEqInt». После ключевого слова where идет перечисление определений методов класса в применении к конкретному экземпляру.
Функция primEqInt должна иметь тип Int -> Int -> Bool
Классы и типы данных являются независимыми друг от друга, они могут быть определены вне всякой связи друг с другом. И только использование ключевого слова instance позволяет связать типы данных и классы.
Для небольшого облегчения труда разработчика программного обеспечения в языке Haskell имеются средства для автоматического указания транслятору, что некоторые достаточно простые типы данных являются экземплярами определенных классов. Такими классами являются классы Eq, Ord, Enum, Bounded,Show и Read. В свою очередь, автоматически определить экземпляры этих классов можно для достаточно простых типов данных, которыми, в принципе, являются любые типы, которые не связаны с обработкой числовых значений с плавающей точкой.
Чтобы автоматически построить экземпляры классов, необходимо перечислить эти классы в круглых скобках через запятую после ключевого слова deriving в определении типа данных.
data Color = Red
| Green
|…
| Custom Int Int Int -- R G B components
deriving (Eq, Ord, …)
deriving (Eq, Ord) тип Color связ-ся с Eq и Ord
В принципе, можно описать любой класс таким образом, чтобы для него можно было автоматически построить экземпляры. Это прерогатива так называемого «политипического» программирования.
