在存在数据族的情况下键入(输入)等式

Type (in)equalities in the presence of data families

我有一个类型族,它确定某物是否位于类型级列表的头部。

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 的异构列表中投影元素。)

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 UserInt 不相等的判断,即使 ID 是单射 data family (因此原则上只等于(减少到) ID User).

我对约束求解器将接受和不接受什么的直觉相当薄弱:我觉得这应该可以编译。谁能解释为什么我的代码不进行类型检查?有没有办法哄 GHC 接受它,也许是通过证明一个定理?

原来这是 known GHC bug。修复程序已经在 GHC head 中,并且应该在下一个即将发布的版本中(GHC 8.0.1 和可能是 7.10.3)。

除此之外,@luqui 关于新型包装器的建议似乎是最简单的选择。