理解HList的定义

6

我对Haskell还比较陌生,正尝试理解HList的其中一个定义。

data instance HList '[] = HNil
newtype instance HList (x ': xs) = HCons1 (x, HList xs)
pattern HCons x xs = HCons1 (x, xs)

我有几个具体的问题:

  • 我看到的'[](x ': xs)语法是什么?它几乎看起来像是对可变类型参数进行模式匹配,但我从未见过这种语法,也不熟悉Haskell中的可变类型参数。我猜这是GHC的类型家族的一部分,但我在链接页面上没有看到任何关于此的内容,并且在Google中搜索语法相当困难。

  • 除了避免对HCons1进行封箱之外,使用元组的newtype声明是否有任何意义(而不是具有两个字段的data声明)?

2个回答

9

首先,您缺少定义的一部分: data family 声明本身。

data family HList (l :: [*])
data instance HList '[] = HNil
newtype instance HList (x ': xs) = HCons1 (x, HList xs)

这被称为数据家族(在TypeFamilies扩展下可用)。
pattern HCons x xs = HCons1 (x, xs)

这是一个双向模式(可在PatternSynonyms扩展下使用)。

我看到的'[](x ': xs)语法是什么意思?

当您在构造函数前面看到'标记时,它是为了表示它们的提升类型级别对应项。作为一种语法上的便利,提升列表和元组也只需要额外的撇号(我们仍然可以写'[]表示空的类型级别列表和':表示类型级别cons)。所有这些都可通过DataKinds扩展获得。

除了避免HCons1的装箱之外,使用包含元组的newtype声明是否有任何意义?

是的,这是为了确保HList具有可表示角色,这意味着您可以在HList之间进行强制转换1。这有点复杂,不能仅通过一个答案来解释,但以下是一个示例,说明当我们拥有某些内容时,事情并不如我们所希望的。

 data instance HList (x ': xs) = HCons x (HList xs)

不使用newtype instance(也不使用模式),考虑以下与IntBool()表示上等效的newtype

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实例变体,但不适用于data实例,因为涉及到角色问题。(更多信息请参见此处。)

1 从技术上讲,data family 没有整体的角色:每个 instance/newtype 的角色可能不同 - 在这里我们只需要 HCons 的情况是可表示的,因为它是被强制转换的那一个。查看此 Trac ticket


(l :: [*]) 是否意味着类型参数 l 受到了 [*] 类型约束? - lcmylin
1
@Textfield 没错!这是一个具有提升类型列表的类型参数。想一想,要让它编译通过可能需要打开 KindSignatures,并且可能还需要导入 Data.Kind... 只需按照 GHC 建议的做即可。 :) - Alec

2
'[]'和'(x ': xs)'是类型级列表的语法,意味着DataKinds语言扩展允许将类型提升为种类,将构造函数提升为类型。即,如果k是某个种类,则'[k]也是一种种类,而'[]是一种种类为'[k]的类型;若t :: kts :: '[k],则t ': ts :: '[k]。所有元素都向右移动一个位置。
因此,在HList (x ': xs)中,xxs匹配两种类型:x匹配一种“正常”的类型,其种类为*(例如Int),而xs匹配另一种种类为'[*]的类型级列表。右侧定义了一个具有类型(x, HList xs)参数的HCons1构造函数的(newtype)数据类型。
例如,我们可以有:
HCons1 (1, HCons1 (True, HNil)) :: HList '[Int, Bool]

或者,使用模式同义词:
1 `HCons` True `HCons` HNil :: HList '[Int, Bool]

关于第二个问题,为什么它被表示为一个带有元组的新类型,我没有一个很好的答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接