Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell中的重叠类型类实例_Haskell_Compiler Errors_Typeclass_Type Safety - Fatal编程技术网

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

我正在用Haskell编写一个几何体库,它充分利用类型类和类型检查器来帮助强制几何操作的有效性。但是编译器抱怨我有重叠的实例。下面是一个简单的例子,我用
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