我有一个类型系列,用于确定某些内容是否属于类型级列表的开头。
type family AtHead x xs where
AtHead x (x ': xs) = True
AtHead y (x ': xs) = False
我想构建这个结果的单例代表。这适用于简单类型的列表。
data Booly b where
Truey :: Booly True
Falsey :: Booly False
test1 :: Booly (AtHead Char [Char, Int])
test1 = Truey
test2 :: Booly (AtHead Int [Char, Int])
test2 = Falsey
但我真正想要做的是为索引data family
的成员列表构造此值。 (实际上,我试图根据类型从ID
s的异构列表中投射元素。)
data family ID a
data User = User
newtype instance ID User = UserId Int
当我们正在寻找的ID
位于列表的首位时,此功能正常运行。
test3 :: Booly (AtHead (ID User) [ID User, Char])
test3 = Truey
但它失败了。
test4 :: Booly (AtHead (ID User) [Int, ID User])
test4 = Falsey
Couldn't match type ‘AtHead (ID User) '[Int, ID User]’
with ‘'False’
Expected type: Booly (AtHead (ID User) '[Int, ID User])
Actual type: Booly 'False
In the expression: Falsey
In an equation for ‘test4’: test4 = Falsey
AtHead (ID User) '[Int, ID User]
未与'False
统一。看起来GHC不愿意判断ID User
和Int
是不相等的,即使ID
是一个内射data family
(因此原则上只等于(减少到ID User
)的东西。
我对约束求解器将会接受并且不会接受的直觉相当弱:我觉得这应该是编译的。谁能解释为什么我的代码没有进行类型检查?有没有办法让GHC接受它,也许是通过证明一个定理?
答案 0 :(得分:3)
事实证明这是一个known GHC bug。该修复程序已经在GHC主管中,应该在下一个即将发布的版本中(GHC 8.0.1和7.10.3)。
除此之外,@ luqui建议使用newtype包装似乎是最简单的选择。