【问题标题】:data families use cases数据族用例
【发布时间】:2013-01-07 11:59:29
【问题描述】:

使用类型同义词族的好处很明显——它是类型级函数。

data 系列并非如此 - 所以我的问题是,数据系列的用例是什么?我应该在哪里使用它?

【问题讨论】:

  • 有时您还想拥有自己的新类型,而不是仅仅指向现有类型,将现有类型包装起来,或者只是包含各种字段的普通记录,而不仅仅是现有的同义词一。您可以像使用通常使用 'data' 声明的类型一样使用它们,只是这次表示将根据您提供的类型参数而有所不同。

标签: haskell type-families


【解决方案1】:

一个好处是数据族是单射的,不像类型族。

如果你有

type family TF a
data family DF a

那么你知道DF a ~ DF b 意味着a ~ b,而使用TF,你不会——对于任何a,你可以确定DF a 是一个全新的类型(就像[a]是与 [b] 不同的类型,当然 a ~ b 除外),而类型族可以将多个输入类型映射到同一个现有类型。

第二个是数据族可以部分应用,就像任何其他类型构造函数一样,而类型族不能。

这不是一个特别真实的例子,但例如,你可以这样做:

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)

基本上,DFDF a 本身就是实际的、一流的、合法的类型,就像您使用 data 声明的任何其他类型一样。 TF a 只是一个计算类型的中间形式。

但我想当我想了解数据系列并阅读类似内容时,所有这些都不是很有启发性,或者至少不适合我。

这是我遵循的经验法则。每当您发现自己重复具有类型族的模式时,并且对于每个输入类型,您声明一个新的data 类型以供类型族映射到,最好去掉中间人并使用数据族。

来自vector 库的真实示例。 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 类型只有一个Mutable Vector 类型的不变量,并且它们之间存在一一对应的关系。 Vector 的可变版本始终称为Mutable Vector:这是它的名字,没有别的名字。如果你有一个Mutable Vector,你可以获得对应的不可变Vector 的类型,因为它作为类型参数就在那里。使用type family Mutable,一旦你将它应用于一个参数,它就会评估为一个未指定的结果类型(大概称为MVector,但你不知道),并且你无法向后映射。

【讨论】:

    猜你喜欢
    • 2018-02-22
    • 1970-01-01
    • 2019-02-21
    • 2017-08-05
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多