列表理解与列表列表

时间:2018-03-28 18:21:18

标签: haskell list-comprehension

我无法理解以下代码:

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,那么它将如何返回条件的列表?

1 个答案:

答案 0 :(得分:5)

在您的情况下,逗号后面的部分不是条件,而是第二个生成器。简化后,符号如下所示:

> [ (a, b) | a <- [1..3], b <- [1..2] ]
> [(1,1),(1,2),(2,1),(2,2),(3,1),(3,2)]

上面的示例compherension意味着以下内容:

  1. 浏览列表[1..3],并查看其中的每个元素
  2. 浏览列表[1..2],并查看其中的每个元素
  3. 制作一个元组
  4. 此外,生成器可以依赖于先前生成器的元素,例如:

    > [ (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) ]
    

    逻辑是这样的:

      {li>代表i中的每个0..(length ts - 1)
    1. 浏览is中的每个treePositions (index ts i)
    2. 并生成i : is作为结果