理解 HList 的这个定义

Understanding this definition of HList

我对 Haskell 比较陌生,我正在尝试理解 HList 的定义之一。

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

我有几个具体问题:

'[](x ': xs)DataKinds language extension allows promoting types to kinds and constructors to types 的意义上是类型级列表的语法;即如果 k 是某种类型,那么 '[k] 也是一种类型,并且 '[] 是一种类型 '[k],如果 t :: kts :: '[k],然后 t ': ts :: '[k]。一切都移动了一位。

所以在HList (x ': xs)中,xxs匹配两种类型:x匹配"normal"类型的*(例如Int) 和 xs 匹配另一个种类 '[*] 的类型级列表。右侧定义了一个 (newtype) 数据类型,它有一个构造函数 HCons1,其参数类型为 (x, HList xs)

举个例子,我们可以

HCons1 (1, HCons1 (True, HNil)) :: HList '[Int, Bool]

或者,使用模式同义词:

1 `HCons` True `HCons` HNil :: HList '[Int, Bool]

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

首先,您缺少定义的一部分: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 扩展名下可用)。

What is the '[] and (x ': xs) syntax I'm seeing?

当你在构造函数前面看到 ' 标记时,表示它们的 promoted type-level counterparts. As a syntactic convenience, promoted lists and tuples 也只需要额外的勾号(我们仍然要为空写 '[]类型级列表和 ': 用于类型级缺点。所有这些都可以通过 DataKinds 扩展名获得。

Is there any point in using a newtype declaration with a tuple (instead of a data declaration with two fields) besides avoiding boxing of HCons1?

对,就是保证HList有一个表象role,也就是说可以在HLists1之间进行强制.这有点过于复杂,无法仅在答案中进行解释,但这里有一个示例,说明当我们有

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

而不是 newtype instance(并且没有模式)。考虑以下 newtypes,它们分别等同于 IntBool()

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 变体,因为角色。 (更多关于 here。)


1 从技术上讲,data family 没有作为一个整体的角色:每个 instance/[=25= 的角色可以不同] - 这里我们只需要 HCons 案例具有代表性,因为这是被强制执行的案例。 Check out this Trac ticket.