I have to do projection of a list of lists which returns all combinations with each element from each list. For example:
projection([[1]; [2; 3]]) = [[1; 2]
Here's a tail-recursive version. It's not as fast as some of the other solutions (only 25% faster than your original function), but memory usage is constant, so it works for extremely large result sets.
let cartesian l =
let rec aux f = function
| [] -> f (Seq.singleton [])
| h::t -> aux (fun acc -> f (Seq.collect (fun x -> (Seq.map (fun y -> y::x) h)) acc)) t
aux id l