Haskell中的Matroid类型类(错误)

时间:2015-07-02 14:25:56

标签: haskell greedy

有限拟阵M是一对(E,I),其中E是有限集(称为地集),I是E的子集族(称为独立集)。

加权拟阵是具有权重函数w的拟阵W:E - > Int(正整数)。

我们可以按如下方式定义(加权)matroid类型类:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

class Matroid matroid a where
  weight :: matroid -> a -> Int 
  groundSet :: matroid -> [a]
  indepSet :: [a] -> Bool

然后我们可以为拟阵定义各种算法。例如,选择具有最小权重的基组F.当应用于图表时,这是用于查找最小权重生成树的Kruskal算法。

(加权)拟阵的实例是(加权)图G =(E,w)其中E是边的集合,w是权函数。为了从图中定义一个matroid,我们将地面集作为边E的集合,E的子集F是独立的,当且仅当它是非循环的时。

instance Matroid WGraph Edge where
  weight = wT 
  groundSet = gSet
  indepSet = iSet

type Vertex = Int
type Edge = (Vertex, Vertex)
type Graph = [Edge]
type WtFun = Edge -> Int
type WGraph = (Graph, WtFun)

gSet :: WGraph -> [Edge]
gSet (es,wt) = es 

wT :: WGraph -> (WtFun)
wT (es,wt) = wt
-- stub
iSet :: [Edge] -> Bool
iSet edges = True

但是,如果给出加权图,则以下代码具有类型错误

weightedG = (es, wt)::WGraph
es = [(4,5),(6,7),(5,7)]::[Edge]
wt :: (Edge -> Int)
wt (4,5) = 15
wt (6,7) = 11
wt (5,7) = 9
gs = groundSet weightedG

No instance for (Matroid WGraph a0)
  arising from a use of `groundSet'
The type variable `a0' is ambiguous

我们如何指定a0应该是Edge类型?

复制/粘贴代码:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

class Matroid matroid a where
  weight :: matroid -> a -> Int 
  groundSet :: matroid -> [a]
  indepSet :: [a] -> Bool

instance Matroid WGraph Edge where
  weight = wT 
  groundSet = gSet
  indepSet = iSet

type Vertex = Int
type Edge = (Vertex, Vertex)
type Graph = [Edge]
type WtFun = Edge -> Int
type WGraph = (Graph, WtFun)

gSet :: WGraph -> [Edge]
gSet (es,wt) = es 

wT :: WGraph -> (WtFun)
wT (es,wt) = wt

-- fix for real implementation
iSet :: [Edge] -> Bool
iSet edges = True

weightedG = (es, wt)::WGraph
es = [(4,5),(6,7),(5,7)]::[Edge]
wt :: (Edge -> Int)
wt (4,5) = 15
wt (6,7) = 11
wt (5,7) = 9
gs = groundSet weightedG

1 个答案:

答案 0 :(得分:3)

错误消息表明GHC不知道Matroid所需的weightedG个实例。

它知道你想要某种类型Matroid WGraph a的{​​{1}},而且你有。{1}} 定义了一个实例a,但由于类型类是开放的,GHC无法断定Matroid Graph Edge必须是a。稍后或在另一个模块中,您(或其他人)可以定义Edge实例 - 例如。

解决这个问题的一种方法是在matroid类型和元素类型之间引入功能依赖,如下所示:

Matroid WGraph String

这告诉GHC {-# LANGUAGE FunctionalDependencies #-} class Matroid matroid a | matroid -> a where ... 类型确定边缘类型matroid。通过这个改变,我得到了你的代码来编译。