我目前正在尝试为Haskell编写GraphML阅读器(请参见this previous question)。由于我对Haskell还是很陌生,尽管学习难度很大,但我还没有完全学会仅从Hackage文档中推断示例的能力。

我目前拥有的是一个Graph实例:

data Graph = Graph
  { graphId :: String,
    nodes :: [String],
    edges :: [(String, String)] -- (Source, target)
  }
  deriving (Show, Eq)


我想将它们转换为Data.Graph。我假设graphFromEdgesgraphFromEdges'是执行此操作的正确函数。

我目前的尝试是创建3元组(nodeid, nodeid, [edge targets])

-- Convert a graph node into a Data.Graph-usable
getDataGraphNode :: Graph -> String -> (String, String, [String])
getDataGraphNode graph node = (node, node, getTargets node graph)

-- Convert a Graph instance into a Data.Graph list of (node, nodeid, edge) tuples
getDataGraphNodeList :: Graph -> [(String, String, [String])]
getDataGraphNodeList graph = map (getDataGraphNode graph) (nodes graph)


但是,由于类型错误,GHC不会编译此代码:

 Couldn't match expected type `[(node0, key0, [key0])]'
            with actual type `(String, String, [String])'


您能指出一个例子,还是最好描述一下从文档中推断出一个例子的一般方法(在这种情况下是函数签名)?我是否需要使用Data.Graph中的Vertex类型?我目前无法确定node0key0类型是什么。

这是一个最小的示例,显示了我在Data.Graph中遇到的问题。我不确定这与滥用类型有什么关系,即使我自己的代码中的许多错误是由于类型系统的问题而发生的:

import Data.Graph
main = do
    graph <- graphFromEdges' [("n0","n0",["n1"]), ("n1","n1",["n2"]), ("n2","n2",[])]
    -- This should print ["n0","n1","n2"]
    print $ vertices graph


它产生以下错误信息:

bar.hs:4:5:
Couldn't match type `IO' with `(,) Graph'
    Expected type: (Graph, ())
      Actual type: IO ()
    In a stmt of a 'do' block: print $ vertices graph
    In the expression:
      do { graph <- graphFromEdges'
                      [("n0", "n0", ["n1"]), ("n1", "n1", ["n2"]), ....];
           print $ vertices graph }
    In an equation for `main':
        main
          = do { graph <- graphFromEdges' [("n0", "n0", [...]), ....];
                 print $ vertices graph }

bar.hs:4:22:
    Couldn't match type `Vertex -> ([Char], [Char], [[Char]])'
                  with `GHC.Arr.Array Vertex [Vertex]'
    Expected type: Graph
      Actual type: Vertex -> ([Char], [Char], [[Char]])
    In the first argument of `vertices', namely `graph'
    In the second argument of `($)', namely `vertices graph'
    In a stmt of a 'do' block: print $ vertices graph

最佳答案

试试这个:

import Data.Graph
main = do
    let (graph, vertexMap) = graphFromEdges' [("n0","n0",["n1"]), ("n1","n1",["n2"]),("n2","n2",[])]
    -- This should print ["n0","n1","n2"]
    print $ map ((\ (vid, _, _) -> vid) . vertexMap) (vertices graph)


graphFromEdges'返回一对值,而Graph是该对中的第一个。同样,在这种情况下,<-用于返回IO something的事物,而graphFromEdges'返回纯值。

关键错误是:

Couldn't match type `IO' with `(,) Graph'
    Expected type: (Graph, ())
      Actual type: IO ()


尽管报告的方式有些误导-如果您给main类型签名main :: IO (),则该报告会更好。通常,如果您对类型错误感到困惑,则值得尝试确定您认为应该是哪种类型,并使用显式类型签名。

10-07 15:14