没有任何特殊进口,组合

时间:2018-03-16 03:31:21

标签: list haskell

我正在尝试获取列表的所有组合。 [1,2,3]的结果应为[(1,2),(1,3),(2,3)]。但是,我在下面的实现提供了[(1,2),(2,3)]

parings [d] = []
parings (y:ys) = (y, head ys): parings ys

3 个答案:

答案 0 :(得分:2)

9000答案中提到的列表理解可以简单地考虑到map电话中。

pairwise :: [a] -> [(a, a)]
pairwise [] = []
pairwise (x:xs) = map (\y -> (x, y)) xs ++ pairwise xs

每个列表理解都可以考虑到mapfilterconcatMap的某种组合,可能会散布一些let个绑定。这样做是学习如何操作函数的好习惯。

答案 1 :(得分:1)

以下是使用tails中的Data.List的一个实现:

import Data.List

pairings :: [a] -> [(a, a)]
pairings = concatMap makePairs . tails
    where
    makePairs [] = []
    makePairs (x:xs) = fmap ((,) x) xs

注意:

  • 我不知道tails是否算作特殊导入"对于你 - 尽管它不在Prelude中,它可以在 base 库中找到,它始终可用。

  • 要了解tails的作用,请尝试tails [1..3]

  • ((,) x)只是撰写(\y -> (x, y))的简洁方式。如果您发现它很难看,您可以改为编写较长版本,或启用TupleSections扩展名并将其拼写为(x,)

  • makePairs可能在没有显式递归的情况下编写为......

    makePairs = maybe [] (\(x, xs) -> fmap ((,) x) xs) . uncons
    

    ... uncons中也可以找到Data.List

  • 这里答案中的所有实现都有一个并非无关紧要的问题:它们在内存中保留了消耗的列表段。要查看我正在谈论的内容,请在GHCi中运行head . drop 8000000 $ pairings [1..]时查看内存使用情况。我对此没有确凿的解决方法 - 例如,一个简单的concat . tails似乎遇到了同样的问题,而fmap makePairs . tails没有(甚至{{ 1}}不会吃掉你所有的记忆。

答案 2 :(得分:0)

我不知道你为什么反对列表理解;与他们一起,解决方案是微不足道的:

pairwise :: [a] -> [(a, a)]
pairwise [] = []
pairwise (x:xs) = [(x, y) | y <- xs] ++ pairwise xs

如果需要,可以将理解分解为具有显式尾递归的单独函数。

(通过保持++两侧的参数并具有累加器参数,整个事物也可以进行尾递归。)