Haskell列表的嵌套笛卡尔积

时间:2010-04-11 06:54:11

标签: haskell list-comprehension

我想制作一个方法,我可以给它一个长度列表,它会返回笛卡尔坐标的所有组合,直到这些长度。用例子更容易解释:

cart [2,5]
Prelude> [ [0,0],[0,1],[0,2],[0,3],[0,4],[1,0],[1,1],[1,2],[1,3],[1,4] ]

cart [2,2,2]
Prelude> [ [0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1] ]

简单的列表理解不起作用,因为我不知道列表将持续多长时间。虽然我喜欢Haskell对于许多问题的简单性,但是我可以在5分钟内编写程序(用C或其他东西),而Haskell给我一个动脉瘤!

这个特定问题的解决方案可以帮助我很多;在处理这样的事情时,我也很想听听你的思考过程。

3 个答案:

答案 0 :(得分:13)

嗯..

cart = sequence . map (enumFromTo 0 . subtract 1)

期望[[a]] -> [[a]]函数执行我们期望的库中已存在的函数是合理的。因此,如果一个人不熟悉sequence,那么发现它只是hoogling的简单问题。

编辑:正如newacct所指出的那样:

cart = mapM (enumFromTo 0 . subtract 1)

也可以通过将之前的解决方案提供给HLint来找到。

答案 1 :(得分:12)

这可以递归地解决。首先,Cartesian product of nothing是{∅}:

cart [] = [[]]

(或者,如果空产品无效,则仅定义1元素形式:

cart [x] = [[i] | i <- [0 .. x-1]]

然后,x:xs的笛卡尔积可以写为

cart (x:xs) = [i:rest | i <- [0 .. x-1], rest <- cart xs]

一般来说,如果你要编写一个需要列表长度为 N 的函数 f ,那么试着想办法让 f(N) 取决于较小的列表,例如仅 f(N - 1),然后求解基本情况 f(0) f(1)等。这将问题转化为一个可以轻松解决的递归。

答案 2 :(得分:7)

我打赌你的程序解决方案会涉及递归。我们的Haskell解决方案也将涉及递归。

所以,递归。首先是递归案例。

cart (c : cs) = [i : r | i <- [0 .. c-1], r <- rcart]
  where rcart = cart cs

这里我们只是说,对于每个可能的初始坐标,以及剩余长度的笛卡尔坐标的每个可能组合,我们明确地将坐标与其余坐标结合起来。

然后是基本情况。

cart [] = [[]]

您可能会想cart [] = []。我起初做了。但想想基本情况下递归案例需要什么。