Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested cartesian product of Haskell lists

I would like to make a method where I could give it a list of lengths and it would return all combinations of cartesian coordinates up to those lengths. Easier to explain with an example:

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] ]

A simple list comprehension won't work because I don't know how long the lists are going to be. While I love Haskell's simplicity for many problems, this is one that I could write procedurally (in C or something) in 5 minutes whereas Haskell gives me an aneurysm!

A solution to this specific problem would help me out a lot; I'd also love to hear about your thought processes when tackling stuff like this.

like image 764
cspyr0 Avatar asked Apr 11 '10 06:04

cspyr0


1 Answers

Umm..

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

It's reasonable to expect that a [[a]] -> [[a]] function doing what we expect already exists in the library. So if one is not familiar with sequence, finding it is a simple matter of hoogling it.

Edit: as newacct pointed out:

cart = mapM (enumFromTo 0 . subtract 1)

This can also be found by feeding the previous solution to HLint.

like image 72
yairchu Avatar answered Sep 23 '22 08:09

yairchu