需要发生的是,列表需要在每个可能的点进行拆分,这样做会使列表更小。需要累积子列表的树,然后将所有内容组合起来。
data Tree
= L {-# UNPACK #-} !Int
| N !Tree !Tree
deriving (Eq, Ord, Read, Show)
-- Convert a list of Ints into a list of Trees containing the given list.
toTrees :: [Int] -> [Tree]
-- We start with the base cases: 0 and 1 elements. Because there are no
-- trees of 0 length, it returns the empty list in that case.
toTrees [] = []
toTrees [x] = [L x]
-- There is at least two elements in this list, so the split into nonempty
-- lists contains at least one element.
toTrees (x:xs@(y:ys)) = let
-- splitWith uses a difference list to accumulate the left end of the
-- split list.
splitWith :: ([a] -> [a]) -> [a] -> [([a], [a])]
splitWith fn [] = []
splitWith fn as@(a:as') = (fn [], as):splitWith (fn . (:) a) as'
-- Now we use a list comprehension to take the list of trees from each
-- split sublist.
in [
N tl tr |
(ll, lr) <- ([x], xs):splitWith ((:) x . (:) y) ys,
tl <- toTrees ll,
tr <- toTrees lr
]
这给出了预期的结果:
GHCi> toTrees [1, 2, 3, 4, 5]
[N (L 1) (N (L 2) (N (L 3) (N (L 4) (L 5)))),N (L 1) (N (L 2) (N (N (L 3) (L 4)) (L 5))),
N (L 1) (N (N (L 2) (L 3)) (N (L 4) (L 5))),N (L 1) (N (N (L 2) (N (L 3) (L 4))) (L 5)),
N (L 1) (N (N (N (L 2) (L 3)) (L 4)) (L 5)),N (N (L 1) (L 2)) (N (L 3) (N (L 4) (L 5))),
N (N (L 1) (L 2)) (N (N (L 3) (L 4)) (L 5)),N (N (L 1) (N (L 2) (L 3))) (N (L 4) (L 5)),
N (N (N (L 1) (L 2)) (L 3)) (N (L 4) (L 5)),N (N (L 1) (N (L 2) (N (L 3) (L 4)))) (L 5),
N (N (L 1) (N (N (L 2) (L 3)) (L 4))) (L 5),N (N (N (L 1) (L 2)) (N (L 3) (L 4))) (L 5),
N (N (N (L 1) (N (L 2) (L 3))) (L 4)) (L 5),N (N (N (N (L 1) (L 2)) (L 3)) (L 4)) (L 5)]
GHCi> length it
14