理解HList的这个定义

时间:2016-12-14 05:04:36

标签: haskell types ghc type-level-computation data-kinds

我对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's Type Families的一部分,但我在链接页面上看不到任何相关内容,而且在Google中搜索语法相当困难。

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

2 个答案:

答案 0 :(得分:8)

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

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

这称为data familyTypeFamilies扩展名下提供)。

pattern HCons x xs = HCons1 (x, xs)

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

  

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

当你在构造函数前面看到'标记时,它表示它们是promoted type-level counterparts。作为一种语法上的方便,promoted lists and tuples也只需要额外的刻度(我们仍然可以为空类型列表编写'[],为类型级别列表编写':。所有这些可通过DataKinds扩展程序获取。

  

除了避免装箱newtype之外,使用带有元组的HCons1声明(而不是带有两个字段的数据声明)是否有任何意义?

是的,这是为了确保HList具有代表role,这意味着您可以在HList s 1 之间强制执行。这有点过于复杂,只能在答案中解释,但这里有一个例子,当我们有什么事情没有按照我们想要的那样去了

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

而不是newtype instance(并且没有模式)。请考虑以下newtype,它们分别代表性地等同于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 / newtype的角色可能不同 - 这里我们只真的需要HCons案例具有代表性,因为那是被胁迫的案例。 Check out this Trac ticket

答案 1 :(得分:2)

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

因此,在t ': ts :: '[k]中,HList (x ': xs)x匹配两种类型:xs匹配"正常"类型x(例如*)和Int与其他类型级别的xs列表相匹配。右侧定义了一个('[*])数据类型,该数据类型具有构造函数newtype,其参数类型为HCons1

举个例子,我们可以

(x, HList xs)

或者,使用模式同义词:

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

我不能很好地回答你的第二个问题,即为什么它代表一个带有元组的新类型。