如何使用迭代生成给定长度的列表元素的所有组合?

时间:2015-12-08 13:11:12

标签: list haskell

我正在尝试使用iterate编写一个函数,它应该生成元素的所有组合:

f :: [a] -> [[[a]]]
f [1,2] = 
  [ [[1] , [2]]                  -- all combinations of length 1
  , [[1,1],[1,2],[2,1],[2,2]],   -- all combinations of length 2
  , [[1,1,1],... ]               -- all combinations of length 3
  , ...                          -- and so on
  ]                              -- infinitely

我尝试了以下方法

f :: [a] -> [[[a]]]
f list = iterate genLists list

genLists :: [a] -> [[a]]       
genLists list  = [ [k] | k<-list ] 

但是,Hugs给了我以下错误:

Type error in application
*** Expression     : iterate genLists list
*** Term           : genLists
*** Type           : [a] -> [[a]]
*** Does not match : [[a]] -> [[a]]
*** Because        : unification would give infinite type

我真的不知道为什么会收到错误。另外,如何仅使用iterate生成这些组合?我无法导入任何其他模块,因为这是一项任务。

2 个答案:

答案 0 :(得分:2)

让我们看看你收到错误的原因:

iterate  :: (a  -> a    ) -> a -> [a]
genLists :: [a] -> [[a]]

如您所见,iterate采用一个函数来获取并返回相同的类型。但是,genLists并没有这样做。它需要一个列表并返回一个列表列表。

由于您确实需要f :: [a] -> [[[a]]]genLists返回类型实际上很好。但是,它的参数类型是错误的。它必须是genLists :: [[a]] -> [[a]]类型:

f :: [a] -> [[[a]]]
f xs = iterate genLists [[x] | x <- xs]
    where
       genLists yss = [ x : ys | x <- xs , ys <- yss]

答案 1 :(得分:1)

以下是一种可能的实现方式,使用应用程序样式(您可以了解有关here的更多信息)。

import Control.Applicative

f :: [a] -> [[[a]]]
f xs = iterate genLists $ map pure xs
  where
    genLists xss = (:) <$> xs <*> xss

然后,

λ> take 3 $ f [1,2]
[[[1],[2]],[[1,1],[1,2],[2,1],[2,2]],[[1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]]]

如果您不想或不能使用适用的东西,可以选择以下方法:

f :: [a] -> [[[a]]]
f xs = iterate genLists $ map (\x -> [x]) xs
  where
    genLists xss = [y : ys | y <- xs, ys <- xss]