减少对普通类型的满意约束

时间:2018-05-06 13:47:56

标签: haskell ghc type-families constraint-kinds

我理解以下类型系列不应该也不能在GHC中实现:

type family MatchesConstraint c a :: Bool where
  MatchesConstraint c a is True if (c a)
  MatchesConstraint c a is False otherwise

这是有问题的,因为类是开放的,因此MatchesConstraint c a可以为程序的某些部分评估为True,而在其他部分评估为False,这取决于范围内的实例,我想象可能是灾难性的。

但请考虑以下因素:

type family MatchesConstraint c a :: Bool where
  MatchesConstraint c a is True if (c a)
  MatchesConstraint c a doesn't reduce otherwise

这似乎很安全。在我们程序的某些部分,如果实例不在范围内,我们可能无法减少,但我们永远不会有不一致。

我可以在GHC中制作这样的作品吗?

我之所以要求这个,是因为人们可能根据不仅直接输入实例而选择基于类的实例。在我认为的某些情况下,这可能是有用的。

1 个答案:

答案 0 :(得分:0)

我回答了你提出的类似问题here on the cafe

正如@Carl所说,所有实例应该在所有范围内。例外是编译所谓的'orphan instances' - 这是一件很糟糕的事情,很容易避免。

对于此处的记录,方法是在类中使用Associated类型,并使用默认定义。如果你真的很高兴Associated类型抛出一个“没有实例”,那就行了。如果与约束不匹配则出错:

class A t where
  type MatchesA t :: Bool           -- Associated type
  type instance MatchesA t = True   -- default instance
  ...                               -- methods for A

instance A Int where
                                    -- uses default instance for MatchesA
  ...                               -- method implementations as usual

-- undefined :: (MatchesA Int)      -- gives type True
-- undefined :: (MatchesA Bool)     -- gives 'no instance' error

我认为你可以得到一个或者匹配约束 - 请参阅MatchesA或MatchesB的咖啡馆帖子。 (我已经快速测试过,它可能有点不稳定,取决于类型家庭减少的急切程度。)

如果约束条件成立,那么您可以选择使用此方法做一件事,但如果不存在则选择另一件事。所以你能得到的最好的是"未能减少"。在咖啡馆的帖子中,我已经链接到一个(相当古老的)wiki页面,其中包含更全面的方法,它依赖于重叠的实例。相关类型不允许重叠: - (。

编辑 这就是为什么编译器不会以您希望评论中Prelude类的方式公开某些约束是否匹配的深层原因:您可能正在使用匹配的事实来选择另一个类C的某个实例;并且可能还有一个类D,其实例选择取决于C匹配; A, B的实例选择取决于D。所以现在我们有循环依赖。在编译器尚未见到的其他模块中的其他实例中,这可能会进一步复杂化。

因此,wiki页面上所有那些(显然)重复的实例都代表程序员知道所有实例以及它们如何相互依赖,这是编译器无法弄清楚的。