我理解以下类型系列不应该也不能在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中制作这样的作品吗?
我之所以要求这个,是因为人们可能根据不仅直接输入实例而选择基于类的实例。在我认为的某些情况下,这可能是有用的。
答案 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页面上所有那些(显然)重复的实例都代表程序员知道所有实例以及它们如何相互依赖,这是编译器无法弄清楚的。