所以我编写了一个函数,它将列表列表作为参数,并从第一个列表中获取每个元素并将其附加到列表列表中的递归调用函数中。 tail,结果返回从这些列表中选择元素的所有可能组合。
foo :: [[a]] -> [[a]]
foo [] = [[]]
foo (x:xs) = [[(x !! a)] ++ b | a <- [0..length(x)-1], b <- foo xs]
*Main> foo [[1, 2], [3, 4], [5, 6]]
[[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
确实应该如何运作,但每当我将我的功能的第二行改为
时foo [] = []
每当我在类型有效的参数上调用它时,它总是返回一个空列表。什么是重要的?
答案 0 :(得分:4)
使用foo [] = []
,b <- foo xs
最后xs == []
将无法获得任何内容{1}},因为它想从零开始提取b
- 所以列表理解将是空的。
foo [] = [[]]
它最终会b <- [[]]
,所以b
会得到一个[]。
你可以简化一下(所以你不需要昂贵的(!!)
):
foo :: [[a]] -> [[a]]
foo [] = [[]]
foo (xs:xss) = [ y : ys | y <- xs, ys <- foo xss]
我认为这也更容易阅读/解释:从x
获取每个xs
,并将其与xss
的每个组合递归地合并到一个新列表中
foo [] = []
:让我们用一个简单的案例来测试它:
foo [[1],[2]]
= [ y:ys | y <- [1], ys <- foo [ [2] ] ]
= [ 1:ys | ys <- [ y':ys' | y' <- [2], ys' <- foo [] ] ]
= [ 1:ys | ys <- [ 2:ys' | ys' <- [] ] ]
= [ 1:ys | ys <- [] ]
= []
而不是{with foo [] = [[]]
):
foo [[1],[2]]
= [ y:ys | y <- [1], ys <- foo [ [2] ] ]
= [ 1:ys | ys <- [ y':ys' | y' <- [2], ys' <- foo [] ] ]
= [ 1:ys | ys <- [ 2:ys' | ys' <- [[]] ] ]
= [ 1:ys | ys <- [ 2:[] ] ]
= [ 1:[2] ]
= [ [1,2] ]