Наследование в Haskell

Механизм расширения классов типов слегка похож на наследование в объектно-ориентированных языках. Речь идет не о наследовании реализации, а о наследовании интерфейса, поскольку классы типов являются некоторым эквивалентом интерфейсов. 
{- 
Класс типов 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


Комментариев нет:

Отправить комментарий