Haskell:集合上的递归函数

时间:2016-02-14 20:52:30

标签: haskell

我是Haskell的新手,我正在尝试编写一个(某种程度上)基本的递归函数来生成集合的分区。我正在引用这个wiki页面(https://en.wikipedia.org/wiki/Partition_of_a_set)来定义set partition。

我目前有一个产生大部分但不是全部分区的功能:

#O_nas {
      background: transparent url('images/o_nas.png') center center no-repeat;
    }
#O_nas:hover {
      box-shadow: 0px 0px 1px #fff;
    }

正如您所看到的,它缺少separate :: [a] -> [[[a]]] separate [] = [[]] separate (b:bs) = [[b]:s | s <- separate bs] ++ [(b:qs):qss | (qs:qss) <- separate bs] >separate [1,2,3] [[[1],[2],[3]],[[1],[2,3]],[[1,2],[3]],[[1,2,3]]] 变体。

我想知道是否可以轻松修改此功能以满足我的要求,或者是否需要创建一个全新的功能。感谢。

1 个答案:

答案 0 :(得分:3)

问题在于,使用[(b:qs):qss | (qs:qss) <- separate bs],您只会将b添加到每个bs分区的第一个子集中。您希望将其添加到每个子集。

separate (b:bs) = [[b]:s | s <- separate bs]
               ++ (singleModifies (b:) =<< separate bs)

-- | All possibilities of applying a function to exactly one element in the list.
singleModifies :: (a->a) -> [a] -> [[a]]
singleModifies _ [] = []
singleModifies f (x:xs) = (f x:xs) : map (x:) (singleModifies f xs) 

如果您不了解=<<运算符的作用:它会“扁平化”列表的嵌套。 separate bs已生成分区列表;对于其中的每一个,我们都会从singleModifies获得另一个列表,但最后我们对哪个列表来自哪里不感兴趣,所以我们只是join(又名concat)他们一起。写这个的另一种方式是

separate (b:bs) = [[b]:s | s <- separate bs]
               ++ concat [singleModifies (b:) bp | bp <- separate bs]