【发布时间】:2015-01-19 03:37:52
【问题描述】:
我有这段代码 sn-p,它使用了大量的 GHC 扩展:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
import GHC.Exts (Constraint)
data HList :: [*] -> * where
Nil :: HList '[]
Cons :: a -> HList l -> HList (a ': l)
type family All (p :: * -> Constraint) (xs :: HList [*]) :: Constraint where
All p Nil = ()
All p (Cons x xs) = (p x, All p xs)
GHC 抱怨说:
‘HList’ of kind ‘[*] -> *’ is not promotable
In the kind ‘HList [*]’
为什么我不能将HList 提升为一种类型?我使用 GHC 7.8.2 和 7.11 时遇到同样的错误。
当然,使用内置的'[] 就可以了:
type family All (p :: * -> Constraint) (xs :: [*]) :: Constraint where
All p '[] = ()
All p (x ': xs) = (p x, All p xs)
我想使用我自己的HList 而不是'[],因为实际的HList 支持追加并且看起来像这样:
type family (:++:) (xs :: [*]) (ys :: [*]) where
'[] :++: ys = ys
xs :++: '[] = xs
(x ': xs) :++: ys = x ': (xs :++: ys)
data HList :: [*] -> * where
Nil :: HList '[]
Cons :: a -> HList l -> HList (a ': l)
App :: Hlist a -> HList b -> HList (a :++: b)
编辑:主要目标是让 GHC 推断
(All p xs, All p ys) ==> All p (xs :++: ys)
这样我可以写
data Dict :: Constraint -> * where
Dict :: c => Dict c
witness :: Dict (All p xs) -> Dict (All p ys) -> Dict (All p (xs :++: ys))
witness Dict Dict = Dict
我曾希望为附加类型级别列表添加显式表示可以帮助我实现这一目标。是否有另一种方法可以让 GHC 相信上述内容?
【问题讨论】:
-
为什么需要
All才能在HList上?任何时候你需要它,你可以在[*]上使用All,这是你HList的类型参数,即你可以有frobulate :: All (Frobable xs) => HList xs -> Frob -
您不能推广 GADT,因为 GHC 类型系统(或者,更像是一种系统)根本不支持它。您的第二个 HList 并不是特别有意义,因为每个列表都有多种表示形式,并且无论如何您都无法在
:++:上进行模式匹配。我猜你最终想写All p (xs :++: ys) = All p xs :++: All p ys之类的东西,但这行不通。您是否正在尝试使用第二个 HList 解决实际问题? -
我不明白您为什么需要将 HList 提升为 kind。为什么不能使用
'[]?您可以轻松附加“[]”。 -
@user2407038:感谢您提供有用的信息。你是完全正确的,我希望能够说服 GHC
(All p xs, All p ys) => All p (xs :++: ys) => ...,我希望添加一个显式的附加表示会有所帮助。我对您的评论思考得越多,我开始看到您提到的一些问题(缺乏独特的表现形式)。我还有其他方法可以证明(All p xs, All p ys) => All p (xs :++: ys)吗?
标签: haskell gadt type-families data-kinds constraint-kinds