Haskell中的重叠类型类实例
我正在用Haskell编写一个几何体库,它充分利用类型类和类型检查器来帮助强制几何操作的有效性。但是编译器抱怨我有重叠的实例。下面是一个简单的例子,我用Haskell中的重叠类型类实例,haskell,compiler-errors,typeclass,type-safety,Haskell,Compiler Errors,Typeclass,Type Safety,我正在用Haskell编写一个几何体库,它充分利用类型类和类型检查器来帮助强制几何操作的有效性。但是编译器抱怨我有重叠的实例。下面是一个简单的例子,我用Int替换了向量类型以简化代码 {-# LANGUAGE FlexibleInstances, UndecidableInstances #-} class PointSet a where liesIn :: Int -> a -> Bool data Line = Line Int Int class TopVec a
Int
替换了向量类型以简化代码
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class PointSet a where
liesIn :: Int -> a -> Bool
data Line = Line Int Int
class TopVec a where
linearSpan :: a -> Line
instance PointSet Line where
point `liesIn` _ = True
class BoundLinear a where
direction :: a -> Int
instance (BoundLinear bdl) => TopVec bdl where
linearSpan bdline = Line 0 0
instance (BoundLinear bdl) => PointSet bdl where
point `liesIn` bdline = point `liesIn` (linearSpan bdline)
编译器(GHC 6.10.3)抱怨说,由于使用
liesIn
,我的点集行
有重叠实例。匹配的实例是点集行
和(BoundLinear bdl)=>点集bdl
。但这没有意义,因为PointSet
的唯一实例应该是Line
和BoundLinear
的任何实例。应该没有冲突,因为Line
不是BoundLinear
的实例。有人能解释一下吗?“应该没有冲突,因为直线不是BoundLinear的实例。”。这是不真实的,因为类是开放的,有人可以走过来,使BoundedLinear的行和实例保持一致。更严格地说,存在冲突,因为bdl
(自由类型变量)可以实例化为Line
。更严格地说,当确定实例是否重叠时,ghc只查看实例的头部(位于=>
右侧的部分)。您可以启用OverlappingInstances
以使代码通过类型检查器。但您可能不应该这样做,因为OverlappingInstances
太复杂/混乱/脆弱。我在这里看到了一些关于类型族的有趣技巧;我不确定其中一个是否适用于这里。您可以使用一个newtypeBLA=BL{unBL::a}
包装器,并为这些内容编写TopVec
和PointSet
实例,例如实例(BoundLinear bdl)=>TopVec(BL bdl),其中linearSpan(BL bdline)=行0
。然后,您可以选择使用基于BoundLinear
的实例,方法是将您的类型包装在BL
中。如果更准确地说,您想将TopVec
和PointSet
定义为BoundLinear
的超类,那么可以在子类实例的基础上自动构建哪些实例。这样,您就可以等待几年的新GHC版本,或者将其包装到newtype