我正在尝试使用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
生成这些组合?我无法导入任何其他模块,因为这是一项任务。
答案 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]