まず、定義の一部、つまり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)
構文は何ですか?
'
コンストラクターの前にマークが表示されている場合、それは、昇格された型レベルの対応物を示すためのものです。構文上の便宜上、プロモートされたリストとタプルも余分なティックが必要です (そして'[]
、空の型レベル リストと':
型レベル コンスに対しても記述できます。これらはすべて、DataKinds
拡張機能を介して利用できます。
newtype
のボクシングを避ける以外に、(2 つのフィールドを持つデータ宣言の代わりに) タプルを持つ宣言を使用する意味はありHCons1
ますか?
はい、それは がHList
代表的な役割HList
を持っていることを確認することです。つまり、 s 1間で強制できることを意味します。これは少し複雑すぎて答えだけで説明することはできませんが、これは私たちが望むように物事が進まない例です。
data instance HList (x ': xs) = HCons x (HList xs)
newtype instance
(およびパターンなし)の代わりに。、、 とそれぞれnewtype
表現上同等である次の を考えてみましょう。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
(詳細はこちら。)
1技術的には、全体として a の役割はありません。役割は/data family
ごとに異なる可能性があります。ここでは、ケースが強制されるため、表現である必要があるだけです。この Trac チケット をチェックしてください。instance
newtype
HCons