我有一段非常简单的代码如下:
{-# 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
Run Code Online (Sandbox Code Playgroud)
我得到一个与Coverage条件相关的错误,其中一个函数依赖项失败了.我是否需要添加-XUndecidableInstances以允许此操作?或者我如何解决这个问题?谢谢
你的情况的问题不是Int而是e.覆盖条件记录在GHC的手册 Sect中.7.6.3.2.例如上下文的宽松规则并说:
覆盖条件.对于每个功能依赖,电视左侧 - > 右侧电视,S中的每个类型变量(右侧电视)必须出现在S(左侧电视)中,其中S是将类声明中的每个类型变量映射到相应的替换在实例声明中输入.
这在实践中意味着什么?在你的情况,你的函数依赖表示g -> n e,这意味着每个实例的类型记n和e是由表示的类型独特g.现在让我们说你正在定义一个实例
instance Graph SomeTypeG SomeTypeN SomeTypeE where
...
Run Code Online (Sandbox Code Playgroud)
覆盖条件表示出现在SomeTypeE或SomeTypeN必须出现的任何类型变量SomeTypeG.如果不满意会怎么样?我们假设一个类型变量a出现在SomeTypeE但不在SomeTypeG.然后,对于固定,SomeTypeG我们将通过替换不同类型来获得无限数量的可能实例a.
在你的情况下
instance Graph g Int e where
...
Run Code Online (Sandbox Code Playgroud)
e是一个这样的类型变量,所以通过Coverage Condition它必须出现g,这不是真的.因为它没有出现在那里,你的定义意味着它Graph g Int Int是一个实例,Graph g Int (Maybe Char)是另一个实例等,与需要恰好有一个的功能依赖相矛盾.
如果你已经定义了类似的东西
instance Graph g Int Char where
Run Code Online (Sandbox Code Playgroud)
那将是美好的,因为有没有类型变量Int和Char.另一个有效的例子可能是
instance Graph (g2 e) Int e where
Run Code Online (Sandbox Code Playgroud)
g2现在在哪里* -> *.在这种情况下,e出现在g2 e满足覆盖条件的情况下,实际上,e始终是唯一确定的g2 e.