Hi,
the solution that Brian suggests is definitely the best option (in F#). Sequence expressions give you an easier way to express what you mean, so why not use them?
Anyway, if you're doing this just as an excercise, then you can rewrite the nested loop as single recursive function and the outer loop as second (as Imagist suggests):
let product =
let rec outer(n1) =
let rec nested(n2) =
if n2 > 4 then [] else (n1 * n2)::(nested(n2 + 1))
if n1 > 4 then [] else nested(2) @ outer(n1 + 1)
outer(2)
I'm using :: in the nested function to append elements to the beginning and @ to concatenate lists generated by individual nested function calls. The use of @ isn't very efficient and the code also isn't tail-recursive, so better version using accumulator parameter would look like this:
let product =
let rec outer n1 acc =
let rec nested n2 acc =
if n2 > 4 then acc else nested (n2 + 1) ((n1 * n2)::acc)
if n1 > 4 then acc else outer (n1 + 1) (nested 2 acc)
outer 2 [] |> List.rev
Hope this helps!