2012-11-24 93 views
2

我有一个非常简单的代码如下:覆盖率条件失败

{-# 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 

我得到了相关的覆盖条件的误差为函数依赖的一个失败。我需要添加-XUndecidableInstances来允许这个吗?或者我如何解决这个问题?谢谢

+5

你的函数依赖性表明,你选择'g'类型的选择分别决定你的节点和元素类型'n'和'e'。那么,说所有图形类型'g'(不知道关于'g')是否确定节点类型是'Int'? – sabauma

+0

@sabauma,谢谢!我从来不知道覆盖情况如何,但这个小例子显示了我! :-) – luqui

+0

@luqui嘿,我从来没有听说过“覆盖条件”之前。我只是推理代码。 – sabauma

回答

1

您的函数依赖性表示您选择的类型g分别决定您的节点和元素类型n和e。那么,说所有图形类型g(不知道g)是否确定节点类型为Int?

5

您的情况中的问题不是Int而是e。覆盖条件记录在GHC's manual Sect。 7.6.3.2。轻松规则的实例背景并说:

覆盖条件。对于每个函数依赖,电视 - >电视权利,类,每一种类型的变量S(电视)必须出现在S(电视),其中S是取代映射每种类型将类声明中的变量转换为实例声明中的相应类型。

这是什么意思在实践中?在你的情况下,你的函数依赖表示g -> n e,这意味着对于每种情况,由ne表示的类型对于由g表示的类型是唯一的。现在让我们假设你正在定义一个实例

instance Graph SomeTypeG SomeTypeN SomeTypeE where 
    ... 

覆盖率条件说,出现在SomeTypeESomeTypeN任何类型的变量必须出现在SomeTypeG。如果不满意会发生什么?假设类型变量a出现在SomeTypeE中,但不在SomeTypeG中。然后,对于固定的SomeTypeG,我们可以通过用不同的类型代替a来实现无数个可能的实例。

在你的情况

instance Graph g Int e where 
    ... 

e就是这样一个类型的变量,因此受到覆盖条件它必须出现在g,这是不正确的。因为它没有出现在那里,所以你的定义暗示Graph g Int Int是一个实例,Graph g Int (Maybe Char)是另一个实例等,与功能依赖关系相矛盾,要求只有一个实例。

如果您已经定义类似

instance Graph g Int Char where 

那将是美好的,因为有在IntChar没有类型的变量。另一个有效的实例可能是

instance Graph (g2 e) Int e where 

其中g2现在是一种* -> *。在这种情况下,e出现在g2 e中,它满足覆盖条件,实际上,e始终由g2 e唯一确定。