21

型シノニムファミリを使用する利点は明らかです。それは型レベルの関数です。

しかし、データファミリーの場合はそうではありません。私の質問は、データ ファミリーのユースケースとは何ですか? どこで使用すればよいですか?

4

1 に答える 1

23

1つの利点は、型族とは異な​​り、データ型が単射であるということです。

あなたが持っている場合

type family TF a
data family DF a

次に、それは、TFを使用している間は、そうではないことをDF a ~ DF b意味します-型族が複数をマップできる一方で、それが完全に新しい型であることを確認できます(もちろん、とは異なる型と同じです)。同じ既存のタイプにタイプを入力します。a ~ baDF a[a][b]a ~ b

2つ目は、他の型構築子と同様に、データ型を部分的に適用できるのに対し、型族は適用できないことです。

これは特に実際の例ではありませんが、たとえば、次のことができます。

data instance DF Int    = DInt    Int
data instance DF String = DString String

class C t where
    foo :: t Int -> t String

instance C DF where -- notice we are using DF without an argument
                    -- notice also that you can write instances for data families at all,
                    -- unlike type families
    foo (DInt i) = DString (show i)

基本的に、DFそしてDF aそれ自体は、で宣言する他のタイプと同様に、実際のファーストクラスの正当なタイプですdataTF a型に評価される単なる中間形式です。

しかし、私がデータファミリについて疑問に思っていて、同様のことを読んでいたとき、それはすべてあまり啓発的ではなかったか、少なくとも私にとってはそうではなかったと思います。

これが私が通っている経験則です。型族があるというパターンを繰り返していることに気付いたときはいつでも、すべての入力型dataについて、型族がマップする新しい型を宣言するので、仲介者を切り取って、代わりにデータファミリを使用する方がよいでしょう。

ベクターライブラリの実際の例。vectorいくつかの異なる種類のベクトルがあります:ボックス化されたベクトル、ボックス化されていないベクトル、プリミティブベクトル、保存可能なベクトル。タイプごとVectorに、対応する可変MVectorタイプがあります(通常のベクトルは不変です)。したがって、次のようになります。

type family Mutable v :: * -> * -> * -- the result type has two type parameters

module Data.Vector{.Mutable} where
data Vector a = ...
data MVector s a = ...
type instance Mutable Vector = MVector

module Data.Vector.Storable{.Mutable} where
data Vector a = ...
data MVector s a = ...
type instance Mutable Vector = MVector

[etc.]

今ではその代わりに、私はむしろ持っていると思います:

data family Mutable v :: * -> * -> *

module Data.Vector{.Mutable} where
data Vector a = ...
data instance Mutable Vector s a = ...
type MVector = Mutable Vector

module Data.Vector.Storable{.Mutable} where
data Vector a = ...
data instance Mutable Vector s a = ...
type MVector = Mutable Vector

[etc.]

Vectorこれは、すべてのタイプに対して正確に1つのMutable Vectorタイプがあり、それらの間に1対1の対応があるという不変条件をエンコードします。可変バージョンのaVectorは常に呼び出されMutable Vectorます:それはその名前であり、他にはありません。がある場合Mutable Vectorは、対応する不変の型を取得できVectorます。これは、型引数としてそこにあるためです。を使用type family Mutableすると、引数に適用すると、指定されていない結果タイプ(おそらく、と呼ばれMVectorますが、わかりません)に評価され、逆方向にマップする方法がありません。

于 2013-01-07T13:25:27.953 に答える