The desired output for multi-dimensional lists would look like this: combinationsM [[1,2],[3,4]] = [[[1,2],[3,4]],[[3,4],[1,2]]]
Your combinations function handles a list of lists of elements. It simply sees a list, and the items of these lists are lists, but the function does not care about this. For [[1,2], [3,4]] it will thus return:
ghci> combinations [[1,2], [3,4]]
[[[1,2],[1,2]],[[1,2],[3,4]],[[3,4],[1,2]],[[3,4],[3,4]]]
It thus has as combinations two times [1,2], a [1,2] and [3,4], a [3,4] and [1,2], and two times [3,4].
Your function thus already returns combinations of sublists. It simply works with lists of any type.
If you want to remove combinations where you pick the same sublist twice, you can define a helper that picks an element and also returns the list of the remaining elements:
pick :: [a] -> [(a, [a])]
pick [] = []
pick (x:xs) = (x, xs) : map … …
where the … parts are left as an exercise. The function should make a recursive call, and prepend all the lists with x in the map … … part.
This thus means that pick [1,4,2,5] returns [(1, [4,2,5]), (2, [1,4,5]), (4, [1,2,5]), (5, [1,4,2])].
Then we can obtain the combinations without picking the same element twice with:
combinations :: [a] -> [[a]]
combinations xs = [[x, y] | (x, ys) <- pick xs, y <- ys]
It might also be better to return a list of 2-tuples, this adds more context to the return type, since then we know it is impossible that a combination contains a different number of items than 2:
combinations :: [a] -> [[a]]
combinations xs = [(x, y) | (x, ys) <- pick xs, y <- ys]