Перечисления в Haskell

Определение класса типов Enum:
class Enum a where
 -- функции движения по перечислительному типу
 succ, pred :: a -> a
 
 -- всем перечислениям может быть сопоставлен некоторый номер
 toEnum :: Int -> a
 fromEnum :: a -> Int

Итерирование по типу:
Prelude> succ 4
5
Prelude> pred 4
3
Prelude> pred 'c'
'b'
Prelude> succ 'z'
'{'
Prelude> fromEnum 'z'
122
Prelude> toEnum 122 :: Char
'z'


Класс типов Bounded служит для того чтобы указывать верхнюю и нижнюю границы.
class Bounded a where
 minBound, maxBound :: a

Функции succ и pred не определены на самом большом и соответственно самом маленьком значении. Единственный тип который является перечислением, но при этом не является Bounded это Integer, потому что тип Integer трактуется как бесконечный и верхняя граница у него отсутствует.
Prelude> succ False
True
Prelude> succ True
*** Exception: Prelude.Enum.Bool.succ: bad argument
Prelude> minBound :: Bool
False
Prelude> maxBound :: Bool
True
Prelude> minBound :: Int
-2147483648
Prelude> maxBound :: Int
2147483647
Prelude> minBound :: Char
'\NUL'
Prelude> maxBound :: Char
'\1114111'
Prelude> maxBound :: Integer

<interactive>:67:1:
    No instance for (Bounded Integer) arising from a use of maxBound
    In the expression: maxBound :: Integer
    In an equation for it: it = maxBound :: Integer


Пример реализации класса типов:
class (Eq a, Enum a, Bounded a) => SafeEnum a where
  ssucc :: a -> a
  ssucc x | x == maxBound = minBound
          | otherwise = succ x
  
  spred :: a -> a
  spred x | x == minBound = maxBound
          | otherwise = pred x
обе функции которого ведут себя как succ и pred стандартного класса Enum, однако являются тотальными, то есть не останавливаются с ошибкой на наибольшем и наименьшем значениях типа-перечисления соответственно, а обеспечивают циклическое поведение. Класс является расширением ряда классов типов стандартной библиотеки, у него написана реализация по умолчанию его методов, позволяющая объявлять его представителей без необходимости писать какой бы то ни было код. Например, для типа Bool достаточно написать строку
instance SafeEnum Bool
и получить возможность вызывать
GHCi> ssucc False
True
GHCi> ssucc True
False

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

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