【问题标题】:Infinite Loop Haskell无限循环 Haskell
【发布时间】:2016-01-27 12:19:51
【问题描述】:
data Node = Node Char [Node] deriving(Eq)

nodeA = Node 'A' [nodeB, nodeC, nodeD]
nodeB = Node 'B' []
nodeC = Node 'C' [nodeE, nodeF]
nodeD = Node 'D' []
nodeE = Node 'E' [nodeB]
nodeF = Node 'F' [nodeA]

deepTraverse :: Node -> [Char]
deepTraverse (Node c []) = [c]
deepTraverse (Node c ns) = c:(map (\(Node cl nsl)->cl) (buildNodeList (Node c ns) ns))
             where lssToLs lss = foldr (++) [] lss
                   buildNodeList nw nsw = lssToLs (map (\(Node cl nsl)->(if (Node cl nsl) == nw then [(Node cl nsl)]
                                                                         else ((Node cl nsl):(buildNodeList nw nsl)))) nsw)

main :: IO()
main = putStrLn (show (deepTraverse nodeA))

每当我打电话给deepTraverse nodeA 时,它都会挂断。在 ghci 中它确实吐出:

Main*> "ABCEBF

让我怀疑 if 的“then”部分。一段时间以来,我一直在努力解决这个问题,任何帮助将不胜感激。

【问题讨论】:

  • 提示:lssToLs 与标准 concat 函数相同。此外,还有一个名为concatMap 的函数。这些都与您的错误无关;这只是一个路过的评论。
  • 谢谢,我在我的 cmets 中用 concat 给出的答案测试了我的 cmets 中提到的固定版本,它确实工作相同。忘了检查那个的前奏功能。

标签: haskell infinite-loop ghci


【解决方案1】:

在盯着您的代码多年试图弄清楚它应该做什么以及为什么会卡住之后,我想我意识到了这个问题。

nodeF 指向nodeA。 (我才刚刚意识到这一点!)您似乎正在尝试使用 == 运算符来确定您何时返回已经查看过的节点。那是行不通的。

当您说node1 == node2 时,== 运算符将遍历整个树 以查看两个值是否相等。如果它们相等,并且这个结构包含一个无限循环......好吧,那么你的代码将永远循环!试试吧。如果你问nodeA == nodeA,我想你会发现它永远返回。这是你的错误。

解决此问题的唯一方法是在每个 Node 上放置一个真正的唯一标签,并仅比较标签。在 Haskell 中,您无法检查两个变量是否“指向”同一事物;你只能比较两个结构是否具有相同的值,即完全遍历它们。

【讨论】:

  • 我认为它会测试数据类型的构造函数以查看它们是否相等。但是我想这意味着它将扩展节点列表的元素构造函数。因此循环。我想我会测试节点的 Char 部分是否相等。也很抱歉,我在问题中确实说过数据类型表示有向图。并且深度遍历的设计目的是在图形中移动并在到达死胡同时回溯,当它回到起始节点时停止。
  • 如果字符标签应该是唯一的,那么是的,这是正确的解决方案。
  • 是的,我注意到了这个问题。这项工作是给大学的,所以我得问问我的讲师是不是这样。虽然,正如问题所述节点声明名称中的 Char 值,我想会是这种情况。
  • @James “我认为 [(==)] 会测试数据类型的构造函数以查看它们是否相等。”但是您的数据类型只有一个构造函数,因此任何两个值都具有相同的构造函数;所以我不相信你是这么想的!
  • @DanielWagner 我指的是常量的构造函数,而不是类型。例如Node 'A' [nodeB, nodeC, nodeD] 不是 Node Char [Node]
猜你喜欢
  • 1970-01-01
  • 2013-10-05
  • 2011-02-23
  • 1970-01-01
  • 1970-01-01
  • 2012-04-06
  • 1970-01-01
  • 1970-01-01
  • 2018-05-05
相关资源
最近更新 更多