Haskell:加入列表的不同方式

时间:2016-09-03 17:44:03

标签: list haskell

如果我有一个列表[a,b,c,d,e],如何在维持秩序的同时找到将元素加入子列表的各种方法。

输出应该看起来像这样

[ [[a], [b], [c], [d]]
, [[a,b], [c], [d]]
, [[a], [b,c], [d]]
, [[a], [b], [c,d]]
, [[a,b,c], [d]]
, [[a,b], [c,d]]
, [[a,b,c,d]]
]

1 个答案:

答案 0 :(得分:2)

你可以这样做:

sublists :: [a] -> [[[a]]]
sublists [x] = [[[x]]]
sublists (x:xs) = sublists xs >>= \(y:ys) -> [[x]:y:ys, (x:y):ys]

这里的主要见解是没有逻辑方法将此扩展到空列表输入 - 唯一可行的候选者将是sublists [] = [[[]]]但这会引入空列表(在这种情况下您不需要) 。

但是,这会激发一个有用的不变量:内部 - 内部(最里面)列表永远不会是空的(我们确保通过不在[[x]:y:ys, (x:y):ys]中引入空列表来保持这种情况 - 我们唯一一次添加新列表列表[x],他们已经有一个元素)。这可以确保lambda中的模式匹配永远不会失败。

顺便说一句,如果它更清楚,可以使用do notation轻轻地重写:

sublists :: [a] -> [[[a]]]
sublists' [x] = [[[x]]]
sublists' (x:xs) = do
    (y:ys) <- sublists' xs
    [[x]:y:ys, (x:y):ys]

concatMap代替(>>=)

sublists'' :: [a] -> [[[a]]]
sublists'' [x] = [[[x]]]
sublists'' (x:xs) = concatMap (\(y:ys) -> [[x]:y:ys, (x:y):ys]) (sublists'' xs)