Harder than I thought! The first step is to calculate the n-Cartesian product l2, which can be done using a combination of List.fill , combinations and permutations (I find it hard to believe that there is no simpler way to do this, but I did not find them):
def prod[T](lst: List[T], n: Int) = List.fill(n)(lst).flatten.combinations(n).flatMap(_.permutations)
The value of n determined by the size of the list l1 . In your example, prod(l2, 2) will provide us with List(List(1, 1), List(1, 2), List(2, 1), List(2, 2)) . The rest is just a map and zip application. Together we have
prod(l2, l1.size).map(l1.zip(_))
The output for l1 = List('a', 'b', 'c'), l2 = List("1", "2") :
List((a,1), (b,1), (c,1)) List((a,1), (b,1), (c,2)) List((a,1), (b,2), (c,1)) List((a,2), (b,1), (c,1)) List((a,1), (b,2), (c,2)) List((a,2), (b,1), (c,2)) List((a,2), (b,2), (c,1)) List((a,2), (b,2), (c,2))