Haskell 哈斯克尔可以';t匹配类型,声明刚性变量

Haskell 哈斯克尔可以';t匹配类型,声明刚性变量,haskell,types,polymorphism,Haskell,Types,Polymorphism,我是Haskell的新手,我正在为图形及其节点创建一个类型类。因为我需要有向图和无向图,所以 data Node = Node { label :: Char , index :: Int } deriving (Ord, Eq) type Graph edgeType = ([Node], [edgeType]) data Edge = DirectedEdge {h :: Node, t :: Node}

我是Haskell的新手,我正在为图形及其节点创建一个类型类。因为我需要有向图和无向图,所以

data Node = Node { label :: Char
                 , index :: Int
                 } deriving (Ord, Eq)
type Graph edgeType = ([Node], [edgeType])
data Edge = DirectedEdge   {h :: Node, t :: Node}
          | UndirectedEdge {a :: Node, b :: Node}
instance Show Node where
    show n = ['(', label n, ')']
instance Show Edge where
    show (DirectedEdge   h t) = show h ++ "->" ++ show t
    show (UndirectedEdge a b) = show a ++ "-"  ++ show b
所以我在区分有向边和无向边。一个图只能有两种类型的边。我还有以下几点:

nodes :: [Node]
nodes = zipWith Node ['a'..] [0..]

emptyGraph :: [Node] -> Graph edgeType
emptyGraph ns = (ns, [])
到目前为止还不错,不过我正在编写一个函数
connect
,它将一个节点连接到一个现有的图形。理想情况下,我只希望它适用于无向图,但这似乎不是一个选项。相反,我有这样的东西:

connect :: Graph edgeType -> Node -> Graph edgeType
connect (ns, es) n = (n:ns, e:es)
    where e = UndirectedEdge n (head ns)
但这会产生以下错误:

Couldn't match type `edgeType' with `Edge'
  `edgeType' is a rigid type variable bound by
             the type signature for
               connect :: Graph edgeType -> Node -> Graph edgeType

实现我想要实现的目标的最佳方法是什么?

因为您选择了一种特定的边类型,即
,当您使用
无向边
时,结果是您的图形在边类型中不再是多态的。它必须具有以下类型:

connect :: Graph Edge -> Node -> Graph Edge
connect (ns, es) n = (n:ns, e:es)
    where e = UndirectedEdge n (head ns)
由于没有其他类型的边,因此明确使用了
无向边


另一方面,我会在节点上使用严格注释,这是出于良好的卫生考虑:

data Node = Node { label :: !Char
                 , index :: !Int
                 } deriving (Ord, Eq)

您可能希望有两种不同的边类型,而不是
edge

newtype DirectedEdge = DirectedEdge { h :: Node, t :: Node}
newtype UndirectedEdge = UndirectedEdge { a :: Node, b :: Node}
您可能需要某种类型的typeclass,在给定任意边的情况下返回
(节点,节点)

class HasNodeEndpoints a where
  endpoints :: a -> (Node, Node)

-- obvious instances for DirectedEdge and UndirectedEdge
然后,当您想要谈论任意图形时,您将编写在
图形a
上工作的函数,并且可能在
HasNodeEndpoints a=>图形a
上工作。关心图形类型的算法分别适用于有向图和无向图的
graph directedge
graph unddirectedge

另一个自然延伸将标记为有向边和无向边

class HasLabeled a where
  type Label a -- associated type synonym
  label :: a -> Label a
  updateLabel :: a -> (Label a -> Label a) -> a

-- now define data types and instances for labeled directed and undirected edges

谢谢是否有任何方法可以让
组合
仅适用于我定义的无向图<代码>连接::Graph Undirectedge->Node->Graph Undirectedge
不起作用。@这不起作用,因为
Undirectedge
是“构造函数”而不是“类型”。您需要按照Lambdageek所建议的思路来研究解决方案,将边分为两种不同的类型。