scand1sk's answer is almost certainly the approach you should be using here, but as a side note, there's another way of thinking about this problem. What you're doing is in effect lifting the append operation into the applicative functor for lists. This means that using Scalaz you can write the following:
import scalaz._, Scalaz._
val listC = (listA |@| listB)(_ :+ _)
We can think of (_ :+ _)
as a function that takes a list of things, and a single thing of the same type, and returns a new list:
(_ :+ _): ((List[Thing], Thing) => List[Thing])
Scalaz provides an applicative functor instance for lists, so we can in effect create a new function that adds an extra list layer to each of the types above. The weird (x |@| y)(_ :+ _)
syntax says: create just such a function and apply it to x
and y
. And the result is what you're looking for.
And as in the for-comprehension case, if you don't care about order, you can make the operation more efficient by using ::
and flipping the order of the arguments.
For more information, see my similar answer here about the cartesian product in Haskell, this introduction to applicative functors in Scala, or this blog post about making the syntax for this kind of thing a little less ugly in Scala. And of course feel free to ignore all of the above if you don't care.