Haskell图形数据类型表示

5

我希望以以下方式在Haskell中表示图形:

对于每个节点,我想存储它的值和相邻节点的列表。我遇到困难的问题是,我希望将相邻节点存储为对其他节点的引用。

例如,我希望将节点ny存储为(“NY”(l p)),其中l和p是相邻节点,而不是(“NY”(“London”“Paris”))。
我尝试了类似这样的东西:

data Node a = Node { value :: a
                   , neighbors :: [Node a]
                   }deriving (Show)

let n1 = Node {value=1, neighbors=[n2]}
let n2 = Node {value=1, neighbors=[n1 n3]}
let n3 = Node {value=1, neighbors=[n2]}

但是我在let语句中遇到了一个错误。我做错了什么?


1
你可能习惯于在ghci提示符下使用let,但在实际的Haskell程序中,在顶层不需要它。 - Andrew Jaffe
2个回答

7
两个问题:
  1. let 是一个表达式形式,在顶层编译器期望一个声明形式。

  2. 你需要一个单一的绑定嵌套;通过使用三个 let,你将定义分成了三个不同的作用域。

下面的代码可以编译,并且当我请求 n1 时,我得到了预期的无限字符串输出:
module Letnest 
where
data Node a = Node { value :: a
                   , neighbors :: [Node a]
                   } deriving (Show)

n1 = Node {value=1, neighbors=[n2]}
n2 = Node {value=1, neighbors=[n1, n3]}
n3 = Node {value=1, neighbors=[n2]}

3
请注意,n1n3是完全无法区分的(因为它们具有相同的定义),这可能会影响您的应用程序,成为此表示方法的问题。 - Reid Barton

4
我不会用这种方式来表示图形。将节点存储在Map或Array中,并通过它们的键引用它们,而不是直接指向它们,这样更容易保存、加载、维护和处理。
对于你目前的表示方法存在一些问题:
Reid Barton评论道:
注意,n1和n3完全无法区分(因为它们具有相同的定义),这可能是该表示方法的问题,这取决于你的应用程序。
(在Haskell中没有类似Python的is比较)
Norman Ramsey注意到:
我得到了一个无限字符串的输出。

1
我也不会这样表示一个图形,但这是我的作业要求 :) - John Retallack
@John Retallack:哦。我希望下一个作业问题是关于如何表示图形的其他方法。 - yairchu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接