Механизм расширения классов типов слегка похож на наследование в объектно-ориентированных языках. Речь идет не о наследовании реализации, а о наследовании интерфейса, поскольку классы типов являются некоторым эквивалентом интерфейсов.
{- Класс типов Ord параметризован типовым параметром a и имеет в рамках класса типов контекст. Класс типов Ord расширяет класс типов Eq. -} class (Eq a) => Ord a where (<), (<=), (>=), (>) :: a -> a -> Bool -- сигнатуры функций сравнения max, min :: a -> a -> a compare :: a -> a -> Ordering -- более тщательное сравнение двух значений {- Minimal complete definition: either compare or <= -}
Тип Ordering устроен довольно просто.
Prelude> :i Ordering data Ordering = LT | EQ | GT -- Defined in ‘GHC.Types’ instance Bounded Ordering -- Defined in ‘GHC.Enum’ instance Enum Ordering -- Defined in ‘GHC.Enum’ instance Eq Ordering -- Defined in ‘GHC.Classes’ instance Ord Ordering -- Defined in ‘GHC.Classes’ instance Read Ordering -- Defined in ‘GHC.Read’ instance Show Ordering -- Defined in ‘GHC.Show’ instance Monoid Ordering -- Defined in ‘GHC.Base’
В нем определены три конструктора. В типе Bool определены два конструктора True и False. А в типе Ordering определены три конструктора: LT, EQ и GT. Таким образом это перечисление, которое содержит ровно три элемента.
Множественное наследование
Допустимо также и множественное наследование. Можно в качестве интерфейса задавать несколько классов типов, которые расширяют наш классов типов.{- Класс типов MyClass является расширением классов типов Eq и Printable. -} class (Eq a, Printable a) => MyClass a where -- ...
Пример множественного наследования:
{- Пусть существуют два класса типов KnownToGork и KnownToMork, которые предоставляют методы stomp (stab) и doesEnrageGork (doesEnrageMork) соответственно: -} class KnownToGork a where stomp :: a -> a doesEnrageGork :: a -> Bool class KnownToMork a where stab :: a -> a doesEnrageMork :: a -> Bool {- Класса типов KnownToGorkAndMork является расширением обоих этих классов, предоставляя дополнительно метод stompOrStab: -} class (KnownToGork a, KnownToMork a) => KnownToGorkAndMork a where stompOrStab :: a -> a {- Задайте реализацию по умолчанию метода stompOrStab, которая вызывает метод stomp, если переданное ему значение приводит в ярость Морка; вызывает stab, если оно приводит в ярость Горка и вызывает сначала stab, а потом stomp, если оно приводит в ярость их обоих. Если не происходит ничего из вышеперечисленного, метод должен возвращать переданный ему аргумент. -} stompOrStab x | (doesEnrageMork x) && (doesEnrageGork x) = stomp (stab x) | (doesEnrageMork x) = stomp x | (doesEnrageGork x) = stab x | otherwise = x
Комментариев нет:
Отправить комментарий