覆盖条件失败

时间:2012-11-24 06:30:40

标签: haskell

我有一段非常简单的代码如下:

{-# 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以允许此操作?或者我如何解决这个问题?感谢

2 个答案:

答案 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,这意味着对于每个实例,ne表示的类型对于g表示的类型是唯一的。现在让我们假设您正在定义一个实例

instance Graph SomeTypeG SomeTypeN SomeTypeE where
    ...

覆盖条件表示SomeTypeESomeTypeN中显示的任何类型变量都必须显示在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

然后就可以了,因为IntChar中没有类型变量。另一个有效的实例可能是

instance Graph (g2 e) Int e where

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

答案 1 :(得分:1)

您的功能依赖性表示您选择的类型g分别确定您的节点和元素类型n和e。那么,说所有图形类型g(对g一无所知)确定节点类型为Int是否有意义?