我无法理解以下代码:
treePositions :: Tree a -> [[Int]]
treePositions (Node _ ts) =
[] : [ (i : is ) | i <- [0..(length ts - 1)],
is <- treePositions (index ts i) ]
此函数将计算给定树中某个位置的任何有效路径,其中每个节点的边缘都标有0..lastOutgoingEdge。 如果我理解正确,索引函数将返回树的节点列表中的索引i处的节点。
index :: [a] -> Int -> a
index :: [a] -> Int -> a
index [] i = error "invalid index"
index (x:xs) 0 = x
index (x:xs) i = ith xs (i-1)
现在对于给定的树:
t1 = Node "a" [
Node "b" [
Node "c"[],
Node "d"[]
]
]
t2 = Node "z" []
该函数将返回:
treePositions t1 == [ [], [0], [0,0], [0,1] ]
treePositions t2 == [ [] ]
我不明白的是这一部分:
[] : [ (i : is ) | i <- [0..(length ts - 1)],is <- treePositions (index ts i) ]
我的想法:
如果我有x|x <- [0..10], x < 2
。这将转换为“将[0..10]
应用于x < 2
中的每个x。因此,如果我将[0..(length ts - 1)]
中的每个i,那么它将如何返回条件的列表?
答案 0 :(得分:5)
在您的情况下,逗号后面的部分不是条件,而是第二个生成器。简化后,符号如下所示:
> [ (a, b) | a <- [1..3], b <- [1..2] ]
> [(1,1),(1,2),(2,1),(2,2),(3,1),(3,2)]
上面的示例compherension意味着以下内容:
[1..3]
,并查看其中的每个元素[1..2]
,并查看其中的每个元素此外,生成器可以依赖于先前生成器的元素,例如:
> [ (a, b) | a <- [1..3], b <- [1..a] ]
> [(1,1),(2,1),(2,2),(3,1),(3,2),(3,3)]
所以在你的情况下:
[ (i : is ) | i <- [0..(length ts - 1)],is <- treePositions (index ts i) ]
逻辑是这样的:
i
中的每个0..(length ts - 1)
,
is
中的每个treePositions (index ts i)
,i : is
作为结果