Haskell列表的嵌套笛卡尔积

csp*_*yr0 9 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] ]
Run Code Online (Sandbox Code Playgroud)

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

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

yai*_*chu 13

嗯..

cart = sequence . map (enumFromTo 0 . subtract 1)
Run Code Online (Sandbox Code Playgroud)

期望[[a]] -> [[a]]函数执行我们期望的函数已经存在于库中是合理的.所以,如果一个不熟悉sequence,发现它是一个简单的事情hoogling它.

编辑:正如newacct所指出:

cart = mapM (enumFromTo 0 . subtract 1)
Run Code Online (Sandbox Code Playgroud)

通过将先前的解决方案提供给HLint也可以找到这一点.

  • `cart = mapM(enumFromTo 0.减1)` (4认同)

ken*_*ytm 12

这可以递归地解决.首先,没有任何东西笛卡尔积是{∅}:

cart [] = [[]]
Run Code Online (Sandbox Code Playgroud)

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

cart [x] = [[i] | i <- [0 .. x-1]]
Run Code Online (Sandbox Code Playgroud)

)

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

cart (x:xs) = [i:rest | i <- [0 .. x-1], rest <- cart xs]
Run Code Online (Sandbox Code Playgroud)

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


dav*_*420 7

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

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

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

在这里,我们只是说,对于每个可能的初始坐标,并且从剩余的长度笛卡尔坐标的每个可能的组合,我们做的统筹与剩余的坐标相结合的明显的事情.

然后是基础案例.

cart [] = [[]]
Run Code Online (Sandbox Code Playgroud)

你可能会想cart [] = [].我起初做了.但想想基本案例中递归案例需要什么.