haskell - 从边列表构造树: missing Leaf nodes

标签 haskell ghci

我编写了下面的代码来构造一棵树,该树具有给定的顶点以及顶点之间的连接列表。

type Connection = (Int,Int)
data Tree = Leaf Int | Node Int [Tree] deriving (Eq,Read,Show)

makeTree :: Int -> [Connection] -> Tree
makeTree x [] = Leaf x
makeTree indx connections =  Node indx otherTrees where
  otherTrees = [makeTree i cx | i <- directConnections, let cx = removeConnectionsTo indx connections]
  directConnections = map (\(x,y) -> if (x == indx) then y else x) $ filter (\(x,y) -> x == indx || y   == indx) connections

removeConnectionsTo :: Int -> [Connection] -> [Connection]
removeConnectionsTo indx = filter (\(x,y) ->    x /= indx && y /= indx)

出于某种原因,下面的输入给出了令人惊讶的不同结果:

makeTree 1 [(1,2),(1,3)] 给我 Node 1 [Leaf 2,Leaf 3]

makeTree 1 [(1,2),(1,5),(2,3),(2,4),(5,6),(5,7)] 给出me 节点 1 [节点 2 [节点 3 [],节点 4 []],节点 5 [节点 6 [],节点 7 []]]

我正在 OS X 10.8.2 上运行 GHCi 版本 7.4.1。

我不明白为什么我在第一个示例中得到两次 Leaf (正确),但在第二个示例中得到具有空子树列表的节点(不正确)。

最佳答案

一个快速解决方法是在决定是否构建 Leaf 还是 Node 之前检查 otherTrees 是否为空,例如

makeTree indx connections
  | null otherTrees = Leaf indx
  | otherwise       = Node indx otherTrees
  where ...  

为了了解这里发生的情况,让我们添加一些工具:

import Debug.Trace

makeTree :: Int -> [Connection] -> Tree
makeTree ix cs | traceShow (ix, cs) False = undefined
makeTree x [] = ... -- leave rest of the function as before

现在将其加载到 GHCi 中,让我们看看递归调用是什么:

> import Control.DeepSeq
> (show $ makeTree 1 [(1,2),(1,5),(2,3),(2,4),(5,6),(5,7)]) `deepseq` ()
(1,[(1,2),(1,5),(2,3),(2,4),(5,6),(5,7)])
(2,[(2,3),(2,4),(5,6),(5,7)])
(3,[(5,6),(5,7)])
(4,[(5,6),(5,7)])
(5,[(2,3),(2,4),(5,6),(5,7)])
(6,[(2,3),(2,4)])
(7,[(2,3),(2,4)])
()

如您所见,第二个参数中的列表不为空,这就是为什么它与函数的第一个情况不匹配的原因,因此您要么需要像我的示例中那样添加一些额外的检查,要么进行确保过滤掉其余的连接。

关于haskell - 从边列表构造树: missing Leaf nodes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13080197/

相关文章:

arrays - Haskell 位数组

haskell - 派生 Show 的模板 Haskell 数据声明

haskell - 在没有 `Conkin.Traversable` 的情况下将值更改为 `unsafeCoerce` 中的索引

haskell - 错误: parse error on input `='

haskell - 将位转换为 Int8 Haskell

debugging - 如何在 Haskell 中编写 showIt 函数?

haskell - 为什么要为像 'nameless' 这样的 `(->) e` 类型定义一个仿函数实例

haskell - 无法在终端中运行 ghci

haskell - 在 Haskell 中查找列表的最大元素和索引

Haskell 代码行未编译 : "Illegal datatype context"