Haskell - 就像每个循环一样

时间:2014-05-21 23:16:54

标签: haskell for-loop

我有三个列表。我们先说吧 [a,b,c],[d,e]和[f,g,h] 现在我想产生所有可能性。结果始终是以下语法: list1 + elem list2 + elem list3

中的元素

例如: ADF AEG CDF BDF bdg

等等。

目前我不知道。我想使用类似for-each-loop的东西,但它确实在haskell中工作^^你有解决这个问题的一些问题吗?

谢谢!

1 个答案:

答案 0 :(得分:9)

一种方法是使用列表推导,如user2407038建议

allCombinations1 xs ys zs = [(x, y, z) | x <- xs, y <- ys, z <- zs]

同样地,这个列表理解涉及到monadic代码

allCombinations2 xs ys zs = do
    x <- xs
    y <- ys
    z <- zs
    return (x, y, z)

这相当于使用liftM3中的Control.Monad

allCombinations3 = liftM3 (\x y z -> (x, y, z))

您还可以使用forMconcat以命令式方式执行相同的操作:

allCombinations4 xs ys zs = concat . concat . concat $
    forM xs $ \x ->
        forM ys $ \y ->
            forM zs $ \z ->
                return (x, y, z)

但这可能更慢,并且当然不是惯用的Haskell代码。或者,您也可以将sequence用于任意数量的输入,这当然是最通用和最短的输入:

allCombinations5 :: [[a]] -> [[a]]
allCombinations5 = sequence

测试它们:

> allCombinations1 [1, 2] [3, 4] [5, 6]
[(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)]
> allCombinations2 [1, 2] [3, 4] [5, 6]
[(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)]
> allCombinations3 [1, 2] [3, 4] [5, 6]
[(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)]
> allCombinations4 [1, 2] [3, 4] [5, 6]
[(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)]
> allCombinations5 [[1, 2], [3, 4], [5, 6]]
[[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6],[2,4,5],[2,4,6]]

请注意,最后一个不会返回元组列表而是返回列表列表,因为它可用于获取N个输入的差异组合,而不是固定数量的输入。

像Haskell中的大多数事情一样,这个问题可以通过多种方式解决,我确信甚至还有其他方法可以添加到此列表中。就个人而言,如果您想要任意数量的输入,我建议使用sequence,否则建议使用列表理解形式。对于其他Haskellers来说,两者都是非常易读和易懂的