基本用法

啟用 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 型別有三個建構函式:Constr1Constr2Constr3

Constr1 建構函式與使用常規資料宣告宣告的建構函式沒有什麼不同:data DataType a = Constr1 Int a (Foo a) | ...

但是 Constr2 要求 a 有一個 Show 的例項,因此在使用建構函式時,例項需要存在。另一方面,當模式匹配時,aShow 的一個例項的事實進入範圍,所以你可以寫:

foo::DataType a -> String
foo val = case val of
    Constr2 x -> show x
    ...

請注意,Show a 約束不會出現在函式的型別中,並且僅在 -> 右側的程式碼中可見。

Constr3 的型別為 DataType Int,這意味著只要 DataType a 的值為 Constr3,就知道 a ~ Int。此資訊也可以通過模式匹配來恢復。