基本用法
啟用 GADTs 擴充套件後,除常規資料宣告外,還可以宣告廣義代數資料型別,如下所示:
data DataType a where
Constr1 :: Int -> a -> Foo a -> DataType a
Constr2 :: Show a => a -> DataType a
Constr3 :: DataType Int
GADT 宣告明確列出了資料型別具有的所有建構函式的型別。與常規資料型別宣告不同,建構函式的型別可以是任何 N-ary(包括 nullary)函式,最終會導致應用於某些引數的資料型別。
在這種情況下,我們宣稱 DataType 型別有三個建構函式:Constr1,Constr2 和 Constr3。
Constr1 建構函式與使用常規資料宣告宣告的建構函式沒有什麼不同: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。此資訊也可以通過模式匹配來恢復。