Haskell 中的拟阵类型 class(错误)
Matroid type class (error) in Haskell
有限拟阵 M 是一对 (E, I),其中 E 是有限集(称为基集),I 是 E 的子集族(称为独立集)。
加权拟阵是配备了权重函数 w: E -> Int(正整数)的拟阵 W。
我们可以定义一个(加权的)拟阵类型类如下:
{-# 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 是权重函数。要从图中定义拟阵,我们将地面集作为边 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 应该是边类型?
copy/paste的代码:
{-# 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
错误消息表明 GHC 不知道您想要 weightedG
的哪个 Matroid
实例。
它知道您想要 Matroid WGraph a
某种类型 a
,并且您有
定义了一个实例 Matroid Graph Edge
,但由于类型 类 是开放的,因此 GHC 无法断定 a
必须是 Edge
。稍后或在另一个模块中,您(或其他人)可以定义一个 Matroid WGraph String
实例 - 例如。
解决此问题的一种方法是在拟阵类型和元素类型之间引入函数依赖性,如下所示:
{-# LANGUAGE FunctionalDependencies #-}
class Matroid matroid a | matroid -> a where
...
这告诉 GHC matroid
类型决定边类型 a
。通过此更改,我得到了要编译的代码。
有限拟阵 M 是一对 (E, I),其中 E 是有限集(称为基集),I 是 E 的子集族(称为独立集)。
加权拟阵是配备了权重函数 w: E -> Int(正整数)的拟阵 W。
我们可以定义一个(加权的)拟阵类型类如下:
{-# 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 是权重函数。要从图中定义拟阵,我们将地面集作为边 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 应该是边类型?
copy/paste的代码:
{-# 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
错误消息表明 GHC 不知道您想要 weightedG
的哪个 Matroid
实例。
它知道您想要 Matroid WGraph a
某种类型 a
,并且您有
定义了一个实例 Matroid Graph Edge
,但由于类型 类 是开放的,因此 GHC 无法断定 a
必须是 Edge
。稍后或在另一个模块中,您(或其他人)可以定义一个 Matroid WGraph String
实例 - 例如。
解决此问题的一种方法是在拟阵类型和元素类型之间引入函数依赖性,如下所示:
{-# LANGUAGE FunctionalDependencies #-}
class Matroid matroid a | matroid -> a where
...
这告诉 GHC matroid
类型决定边类型 a
。通过此更改,我得到了要编译的代码。