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.
Umm..
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 withsequence
, finding it is a simple matter of hoogling it.Edit: as newacct pointed out:
This can also be found by feeding the previous solution to HLint.
I bet your procedural solution would involve recursion. Our Haskell solution will involve recursion too.
So, recursion. First the recursive case.
Here we're just saying that for each possible initial co-ordinate, and each possible combination of cartesian co-ordinates from the remaining lengths, we do the obvious thing of combining the co-ordinate with the remaining co-ordinates.
Then the base case.
You might think
cart [] = []
. I did at first. But think about what the recursive case requires from the base case.This can be solved recursively. First, the Cartesian product of nothing is {∅}:
(Or define just the 1-element form if the empty product is invalid:
)
Then, the Cartesian product of
x:xs
can be written asIn general, if you what to write a function f that requires the list's length N, try to think of a way to make f(N) depends on smaller lists e.g. f(N - 1) only, then solve the base case f(0) or f(1) etc. This transforms the problem into a recursion that can be easily solved.