Haskell Language
Обобщенные типы алгебраических данных
Поиск…
Основное использование
Когда расширение GADTs
включено, помимо регулярных объявлений данных, вы также можете объявить обобщенные алгебраические типы данных следующим образом:
data DataType a where
Constr1 :: Int -> a -> Foo a -> DataType a
Constr2 :: Show a => a -> DataType a
Constr3 :: DataType Int
В объявлении GADT перечислены типы всех конструкторов, тип данных которых явно указан. В отличие от обычных деклараций типов данных тип конструктора может быть любой N-арной (включая нулевую) функцию, которая в конечном итоге приводит к типу данных, применяемому к некоторым аргументам.
В этом случае мы объявили, что тип DataType
имеет три конструктора: Constr1
, Constr2
и Constr3
.
Конструктор Constr1
не отличается от объявленного с использованием регулярного объявления data DataType a = Constr1 Int a (Foo a) | ...
: data DataType a = Constr1 Int a (Foo a) | ...
Однако Constr2
требует, чтобы a
имел экземпляр Show
, и поэтому при использовании конструктора экземпляр должен существовать. С другой стороны, при сопоставлении шаблонов на нем появляется тот факт, что a
является экземпляром Show
, поэтому вы можете написать:
foo :: DataType a -> String
foo val = case val of
Constr2 x -> show x
...
Обратите внимание, что параметр Show a
ограничение не отображается в типе функции и отображается только в коде справа от ->
.
Constr3
имеет тип DataType Int
, что означает, что всякий раз, когда значение типа DataType a
является Constr3
, известно, что a ~ Int
. Эта информация также может быть восстановлена с совпадением шаблонов.