タイプの利点同義語ファミリーは明確です - それはタイプレベルの機能です。データファミリの使用例
しかし、データファミリではそうではありません - 私の質問は、データファミリの使用ケースですか?どこで使うべきですか?
タイプの利点同義語ファミリーは明確です - それはタイプレベルの機能です。データファミリの使用例
しかし、データファミリではそうではありません - 私の質問は、データファミリの使用ケースですか?どこで使うべきですか?
利点の1つは、データファミリがタイプファミリとは異なり、注入型であることです。
あなたは
type family TF a
data family DF a
を持っているなら、あなたはTFと、あなたがいない間、DF a ~ DF b
は、そのa ~ b
を意味することを知っている - と同じように(任意のa
のためにあなたがDF a
は全く新しいタイプであることを確認することができます[a]
はa ~ b
以外の場合は[b]
とは異なるタイプですが、タイプファミリーは複数の入力タイプを同じ既存タイプにマップできます。
もう1つは、他のタイプのコンストラクタと同様にデータファミリを部分的に適用できることですが、タイプファミリは適用できません。
は、これは特に、現実世界の例ではなく、例えば、あなたが行うことができます:
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
は他と同じように、自分自身で実際、ファーストクラス、正当な種類の、ありますdata
と宣言してください。 TF a
は、型に評価される中間形式に過ぎません。
しかし、私はデータファミリーについて疑問を持ち、同様のことを読んでいたときに、それはあまり啓発されていないか、少なくとも私のためではなかったと思います。
私が行った経験則があります。タイプファミリを持つパターンを繰り返すと、入力タイプごとにタイプファミリに新しいタイプのdata
が配置されると宣言すると、仲介人を省略して代わりにデータファミリを使用する方が良いでしょう。
vectorライブラリーの実際の例です。 vector
にはいくつかの異なる種類のベクターがあります。ボックス化されたベクター、ボックス化されていないベクター、プリミティブベクター、保存可能なベクターです。各Vector
タイプに対応する変更可能なMVector
タイプ(通常のベクトルは不変です)があります。だから、それは次のようになります。すべてのVector
タイプのために、正確に一つのMutable Vector
タイプがあることを不変エンコード
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.]
を、そこにあること:
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.]
を今すぐその代わりに、私はむしろだろうそれらの間に1対1の対応関係があります。 Vector
の変更可能なバージョンは、常にMutable Vector
と呼ばれます。名前はその名前であり、他にはありません。 Mutable Vector
をお持ちの場合は、対応する不変のタイプVector
を得ることができます。これは、型引数として存在するためです。 type family Mutable
を指定すると、それを引数に適用すると、不特定の結果の型(おそらくMVector
と呼ばれますが、わかりません)に評価され、逆方向にマップする方法はありません。
既存のタイプを指すのではなく、既存のタイプと同じ意味の新しいシノニムではなく、さまざまなフィールドを持つ既存のタイプまたは通常のレコードをラップする、独自の新タイプを使用することもできます。 'data'で宣言された型を使うのと同じように、これを使うことができます。ただし、今度は型引数に応じて表現が異なることがあります。 –