I'm trying to convert a tuple of lists of the same length:
([Int], [Int], ..)
to a list of tuples [(Int, Int, ...)]
. This can be accomplished for predetermined sizes with the following code:
buildList :: ([a], [a], [a], [a], [a], [a], [a], [a]) -> [(a, a, a, a, a, a, a, a)]
buildList ([], [], [], [], [], [], [], []) = []
buildList (a:as, b:bs, c:cs, d:ds, e:es, f:fs, g:gs, h:hs) = (a, b, c, d, e, f, g, h) : buildList (as, bs, cs, ds, es, fs, gs, hs)
As you can probably see, this isn't going to be pretty when I need a lot of items in the list, and it would be much cleaner if it worked for any arbitrary value.
So my questions is, do you have a function that preforms this operation for tuples of arbitrary length?
As is usual with this kind of questions, the answer to 'should you' and 'can you' are different. Here, I will answer strictly the second.
The first part of solving this is a representation of n-ary tuples, or (to sound extra fancy) products. Let's do that (without using any imports so that the whole thing remains self-contained, and also because on the machine I'm currently on, Stack is misbehaving):
So this gives us a way to write something like
Using this type, at least we can start thinking about what the type of our n-ary zipping function
zipN
should be:however, we still need a way to somehow convert that tuple-of-lists
Product '[[a], [b], ...]
into a tuple-of-elementsProduct '[a, b, ...]
. What I've found easiest is using an associated type family to do the conversion and the actual zipping in lockstep:Example:
Note that this behaves like regular
zip
in that the result list's length is specified by the shortest list in the tuple.