Haskell列表

时间:2016-02-16 04:41:20

标签: list haskell

我需要编写一个函数来生成列表的所有可能分区,包括非连续分区。看起来应该是这样的:

*Main> ps [1,2,3,4]
[[21, 3, 4],[31, 2, 4],[41, 2, 3],[431, 2],[21, 43],[4321],[31, 42],[421, 3],[41, 32],[321, 4],[1, 32, 4],[1, 42, 3],[1, 432],[1, 2, 43],[1, 2, 3, 4]]

到目前为止,我只能使用列表推导生成递归函数来生成连续的分区。

ps [] = [[]]
ps (x:xs) = [[x]:qs | qs <- ps xs] ++ [(x:gs):gss | (gs):gss <- ps xs]

我知道移动每个分区的尾部并将其添加到每个分区的第一个元素,但我不确定如何在Haskell中执行此操作。我还是这种语言的新手。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:4)

以下是您需要的功能:

bloat :: a -> [[a]] -> [[[a]]]
bloat x  []      = [[[x]]]
bloat x (xs:xss) = ((x:xs):xss) : map (xs:) (bloat x xss)

E.g。 bloat 'a' ["b", "c", "de"]等于

[["ab","c","de"],["b","ac","de"],["b","c","ade"],["b","c","de","a"]]

即。将a添加到每个子列表(以及列表末尾)并复制剩余的子列表。

然后partitionSet只是

partitionSet :: [a] -> [[[a]]]
partitionSet  []    = [[]]
partitionSet (x:xs) = [ys | yss <- partitionSet xs, ys <- bloat x yss]

或者更惯用的Haskell

partitionSet :: [a] -> [[[a]]]
partitionSet = foldr (\x r -> r >>= bloat x) [[]]