Q: Scala Match Error Case Prevention I have this function that basically combines Lists of Lists, but you can ignore that, for that is not the issue:
def combinationList[T](ls:List[List[List[T]]]) : List[List[List[T]]] = ls match {
 case head :: Nil  => for(x <- head) yield List(x)
 case head :: tail :: Nil =>
  for {
    hl <- head
    tl <- tail
    if tl.forall(te => !hl.contains(te))
  } yield List(hl, tl)
}

This works when I have a List with two sub-lists but it fails to match when I have more than two. I obviously need to use this function recursively to make a more general case, and I've tried to add the following case at the end of the function:
case _ => combinationList(combinationList(ls.tail):::List(ls.head))

The logic here is that, imagine we have a List with 3 sub lists, like so:
List ( List(1), List(2), List(3) )

When I first call the fucntion, it will only match in the last case I mentioned, so, I will call the function with the list's tail (List(2), List(3)), and, in that call, it will match for the second case (head::tail::Nil), then, when it returns, it should be a single List and when added to the list's original head (List(1)::List(2+3)) it should match on the second condition. The issue here is that the return is not a single list (List(2+3)) but rather yet another combination of lists (List(2), List(3)) so it will obviously recursive forever. I've tried to modify the case like this:
combinationList(List(combinationList(ls.tail)):::List(ls.head))

But it gives me an error ("The expression of type List[List[List[Any]]] doesn't conform to type List[List[List[T]]]"
Any ideas? Thanks.
[EDIT:] This function's purpose is to combine lists in such manner:
simplified input: List( List(1,2), List(3), List(4))
simplified output: List( List(1,3,4), List(2,3,4))

real input: List(
             List(List(1), List(3), List(4)), 
             List(List(2), List(3), List(4))
            )
real expected output: List(
                       List(List(1), List(2)), 
                       List(List(1), List(3)), 
                       List(List(1), List(4)), 
                       List(List(3), List(2)), 
                       List(List(3), List(4)), 
                       List(List(4), List(2)), 
                       List(List(4), List(3))
                      )

With the real input, the function is able to return the expected output, it only fails when another sub list is added, like so:
     input: List(
             List(List(1), List(2)), 
             List(List(3), List(4)),
             List(List(5))
            )

The expected output here, would be:
     expected output: List(
                       List(List(1), List(3), List(5)), 
                       List(List(1), List(4), List(5)), 
                       List(List(2), List(3), List(5)), 
                       List(List(2), List(4), List(5))
                      )

So, the order of the combinations don't really matter much, I can head:::tail or tail:::head, it's the same thing.

A: I still don't know why you want three levels of nesting. However, the following generic method works with all your examples, both with integers and with lists:
def combinationList[T](ls: List[List[T]]): List[List[T]] = {
  def recHelper(remainingLs: List[List[T]], blacklist: Set[T]): List[List[T]] = {
    remainingLs match {
      case Nil => List(Nil)
      case h :: t => for { 
        x <- h.filterNot(blacklist.contains)
        xs <- recHelper(t, blacklist + x)
      } yield x :: xs
    }
  }
  recHelper(ls, Set.empty)
}

This implementation doesn't filter out any combinations with ! .contains, instead it maintains a set of blacklisted elements, and doesn't generate the invalid combinations in the first place.
Some examples:
def showExample[T](input: List[List[T]]): Unit = {
  println("=" * 60)
  println(input)
  println("-" * 60)
  for (c <- combinationList(input)) {
    println("  " + c)
  }
}
showExample(List(List(1, 2), List(3), List(4)))
showExample(List(List(1, 2, 3), List(2, 3, 4), List(2, 3, 5)))
showExample(List(
  List(List(1), List(3), List(4)), 
  List(List(2), List(3), List(4))
))
showExample(List(
  List(List(1), List(2)), 
  List(List(3), List(4)),
  List(List(5))
))

Output:
============================================================
List(List(1, 2), List(3), List(4))
------------------------------------------------------------
  List(1, 3, 4)
  List(2, 3, 4)
============================================================
List(List(1, 2, 3), List(2, 3, 4), List(2, 3, 5))
------------------------------------------------------------
  List(1, 2, 3)
  List(1, 2, 5)
  List(1, 3, 2)
  List(1, 3, 5)
  List(1, 4, 2)
  List(1, 4, 3)
  List(1, 4, 5)
  List(2, 3, 5)
  List(2, 4, 3)
  List(2, 4, 5)
  List(3, 2, 5)
  List(3, 4, 2)
  List(3, 4, 5)
============================================================
List(List(List(1), List(3), List(4)), List(List(2), List(3), List(4)))
------------------------------------------------------------
  List(List(1), List(2))
  List(List(1), List(3))
  List(List(1), List(4))
  List(List(3), List(2))
  List(List(3), List(4))
  List(List(4), List(2))
  List(List(4), List(3))
============================================================
List(List(List(1), List(2)), List(List(3), List(4)), List(List(5)))
------------------------------------------------------------
  List(List(1), List(3), List(5))
  List(List(1), List(4), List(5))
  List(List(2), List(3), List(5))
  List(List(2), List(4), List(5))

Some hints:


*

*The more generic versions of the code are often easier to write, because if there are more constraints, there are fewer possibilities to do something wrong. In this case, the triple nesting seems unnecessary.

*The base case is the empty list, not the list with one element

*The recursion must work with lists of arbitrary length, but x :: y :: Nil matches only lists of length two.

