Haskell Language
Uogólnione algebraiczne typy danych
Szukaj…
Podstawowe użycie
Gdy rozszerzenie GADTs
jest włączone, oprócz zwykłych deklaracji danych można również zadeklarować uogólnione algebraiczne typy danych w następujący sposób:
data DataType a where
Constr1 :: Int -> a -> Foo a -> DataType a
Constr2 :: Show a => a -> DataType a
Constr3 :: DataType Int
Deklaracja GADT wyraźnie wymienia typy wszystkich konstruktorów, których typ danych ma. W przeciwieństwie do zwykłych deklaracji typów danych, typem konstruktora może być dowolna funkcja N-ary (w tym zerowa), która ostatecznie skutkuje typem danych zastosowanym do niektórych argumentów.
W tym przypadku zadeklarowaliśmy, że typ DataType
ma trzy konstruktory: Constr1
, Constr2
i Constr3
.
Konstruktor Constr1
nie różni się od deklarowanego przy użyciu zwykłej deklaracji data DataType a = Constr1 Int a (Foo a) | ...
: data DataType a = Constr1 Int a (Foo a) | ...
Constr2
wymaga jednak, aby a
miało instancję Show
, a więc przy użyciu konstruktora instancja musiałaby istnieć. Z drugiej strony, gdy dopasowuje się do niego wzorzec, wchodzi w zakres fakt, że a
jest instancją Show
, więc możesz napisać:
foo :: DataType a -> String
foo val = case val of
Constr2 x -> show x
...
Zauważ, że Show a
ograniczenie nie pojawia się w typie funkcji i jest widoczne tylko w kodzie po prawej stronie ->
.
Constr3
ma typ Constr3
DataType Int
, co oznacza, że ilekroć wartość typu Constr3
DataType a
jest Constr3
, wiadomo, że a ~ Int
. Te informacje również można odzyskać za pomocą dopasowania wzorca.