Haskell约束的不安全蕴涵

时间:2015-09-09 13:50:59

标签: haskell ghc

我正在使用constraints包(对于GHC Haskell)。我有一个类型系列,用于确定类型级别列表是否包含元素:

type family HasElem (x :: k) (xs :: [k]) where
  HasElem x '[] = False                                                                               
  HasElem x (x ': xs) = True                                                                          
  HasElem x (y ': xs) = HasElem x xs

这是有效的,但它没有给我的一点是知识

HasElem x xs   entails   HasElem x (y ': xs)

因为类型族不是"的归纳定义是"的元素。声明(就像你在agda中一样)。我非常确定,在GADT可以升级到类型级别之前,无法用数据类型表达列表成员资格。

所以,我已经使用constraints包写了这个:

containerEntailsLarger :: Proxy x -> Proxy xs -> Proxy b -> (HasElem x xs ~ True) :- (HasElem x (b ': xs) ~ True)
containerEntailsLarger _ _ _ = unsafeCoerceConstraint

幽灵,但它确实有效。我可以根据需要进行模式匹配以获得我需要的东西。我想知道的是它是否会导致程序崩溃。似乎它不可能,因为unsafeCoerceConstraint被定义为:

unsafeCoerceConstraint = unsafeCoerce refl

在GHC中,类型级别在运行时被省略。我以为我会检查,只是为了确保这样做是可以的。

---编辑---

由于还没有人给出解释,我想我会稍微扩展一下这个问题。在我创造的不安全的蕴涵中,我只期待一个类型的家庭。如果我做了一些涉及类型词典的事情,那就像这样:

badEntailment :: Proxy a -> (Show a) :- (Ord a)
badEntailment _ = unsafeCoerceConstraint

我认为这几乎肯定会导致段错误。这是真的?如果是的话,是什么让它与原版不同?

---编辑2 ---

我只是想提供一些背景知道为什么我对此感兴趣。我的兴趣之一是在Haskell中对关系代数进行可用的编码。我认为无论你如何定义函数来处理类型级列表,都会有明显的事情没有被证明是正确的。例如,我之前拥有的约束(对于半连接)看起来像这样(这是来自内存,因此可能不准确):

semijoin :: ( GetOverlap as bs ~ Overlap inAs inBoth inBs
            , HasElem x as, HasElem x (inAs ++ inBoth ++ inBs)) => ...

所以,对于一个人来说,如果我采用两个集合的联合,它应该包含x中的元素as,那我应该是显而易见的,但我不确定它可能合法地说服了这个约束求解器。所以,这是我做这个伎俩的动机。我创造了欺骗约束解算器的蕴涵,但我不知道它是否真的安全。

0 个答案:

没有答案