我有一段非常简单的代码如下:
{-# LANGUAGE
MultiParamTypeClasses,
FunctionalDependencies,
FlexibleInstances,
FlexibleContexts
#-}
class Graph g n e | g -> n e where
nodes :: g -> [n]
edge :: g -> (n,n) -> Maybe e
instance Graph g Int e where
nodes g = []
edge g (n1,n2) = Nothing
我收到了与Coverage Condition相关的错误,其中一个功能依赖项失败了。我是否需要添加-XUndecidableInstances以允许此操作?或者我如何解决这个问题?感谢
答案 0 :(得分:5)
您的案例中的问题不是Int
,而是e
。覆盖条件记录在GHC's manual Sect中。 7.6.3.2。放宽规则,例如上下文并说:
覆盖条件。对于每个功能依赖,tvs left - >类的TVs right ,S中的每个类型变量(tvs right )必须出现在S(tvs left )中,其中S是替换将类声明中的每个类型变量映射到实例声明中的相应类型。
在实践中意味着什么?在您的情况下,您的函数依赖关系显示g -> n e
,这意味着对于每个实例,n
和e
表示的类型对于g
表示的类型是唯一的。现在让我们假设您正在定义一个实例
instance Graph SomeTypeG SomeTypeN SomeTypeE where
...
覆盖条件表示SomeTypeE
或SomeTypeN
中显示的任何类型变量都必须显示在SomeTypeG
中。如果不满意会怎么样?我们假设类型变量a
出现在SomeTypeE
但不出现在SomeTypeG
中。然后对于固定的SomeTypeG
,我们将通过用a
替换不同的类型来获得无数个可能的实例。
在你的情况下
instance Graph g Int e where
...
e
是一个类型变量,因此通过Coverage条件它必须出现在g
中,这不是真的。因为它没有出现在那里,你的定义意味着Graph g Int Int
是一个实例,Graph g Int (Maybe Char)
是另一个实例等,与要求恰好有一个的功能依赖相矛盾。
如果您定义了类似
的内容instance Graph g Int Char where
然后就可以了,因为Int
和Char
中没有类型变量。另一个有效的实例可能是
instance Graph (g2 e) Int e where
其中g2
现在属于* -> *
。在这种情况下,e
中会显示g2 e
,它会满足覆盖条件,实际上e
始终是g2 e
唯一确定的。
答案 1 :(得分:1)
您的功能依赖性表示您选择的类型g分别确定您的节点和元素类型n和e。那么,说所有图形类型g(对g一无所知)确定节点类型为Int是否有意义?