首先,您缺少部分定義:data family
聲明本身。
data family HList (l :: [*])
data instance HList '[] = HNil
newtype instance HList (x ': xs) = HCons1 (x, HList xs)
這被稱爲data family
(下TypeFamilies
擴展可用)。
pattern HCons x xs = HCons1 (x, xs)
這是一個雙向模式(可在PatternSynonyms
擴展名下獲得)。
什麼是我看到的'[]
和(x ': xs)
語法?
當您在構造函數前面看到'
標記時,表示它們的標記爲promoted type-level counterparts。作爲一個語法上的方便,promoted lists and tuples也只需要額外的蜱(我們仍然可以編寫'[]
爲類型級別利弊空類型級列表和':
。所有這一切都可以通過DataKinds
擴展。
是否有除了避免HCons1
拳擊?
是的,這是確保HList
有代表性role,在使用了元組(而不是有兩個字段的數據聲明)一newtype
聲明的任何點,這意味着你可以控制ce HList
s 。這是一個有點太參與只是一個答案來解釋,但在這裏是那裏的東西不要去,因爲我們希望,當我們有
data instance HList (x ': xs) = HCons x (HList xs)
代替newtype instance
(無圖案)的例子。考慮以下newtype
S的都是表象等同於Int
,Bool
和()
分別
newtype MyInt = MyInt Int
newtype MyBool = MyBool Bool
newtype MyUnit = MyUnit()
回想一下,我們可以使用coerce
包或自動解開這些類型。好了,我們希望能夠做同樣的事情,但對於整個HList
:
ghci> l = (HCons 3 (HCons True (HCons() HNil))) :: HList '[Int, Bool, ()]
ghci> l' = coerce l :: HList '[MyInt, MyBool, MyUnit]
這工作與newtype instance
變種,但不是因爲角色的data instance
之一。 (更多關於該here)
技術上,有一個data family
作爲一個整體沒有任何作用:角色可以爲每個instance
/newtype
不同 - 這裏我們只真正需要的HCons
情況具有代表性,因爲那是被強制執行的。 Check out this Trac ticket。
'(l :: [*])'是否意味着一個類型參數'l'被約束成類型'[*]'? – Textfield
@Textfield正好!一個類型參數是一個提升的類型列表。想想看,編譯出來可能需要打開'KindSignatures',並且可能還需要導入'Data.Kind' ...只要做一下GHC的建議即可。 :) – Alec