Replacing an F# loop over a mutable variable by an immutable approach
I would write it this way

let rec exhaust m i =
    match m % i with
    | 0L -&gt; exhaust (m / i) i
    | _ -&gt; m


Not a huge improvement, but I think it's idiomatic. Now let's look at primeFactors:

let primeFactors x =
    let rec primeFactors' = function
        | (m, _, r) when m = 1L -&gt; r
        | (m, i, r) -&gt;
            let m' = exhaust m i
            primeFactors' (m', (i+1L), (if m &lt;&gt; m' then i::r else r))
    List.rev (primeFactors' (x, 2L, []))


Let's get rid of the when:

let primeFactors x =
    let rec primeFactors' = function
        | (1L, _, r) -&gt; r
        | (m, i, r) -&gt;
            let m' = exhaust m i
            primeFactors' (m', (i+1L), (if m &lt;&gt; m' then i::r else r))
    List.rev (primeFactors' (x, 2L, []))


And tidy up a little

let primeFactors x =
    let rec primeFactors' = function
        | 1L, _, r -&gt; r
        | m, i, r -&gt;
            let m' = exhaust m i
            primeFactors' (m', i + 1L, if m &lt;&gt; m' then i::r else r)
    primeFactors' (x, 2L, []) |&gt; List.rev


I know the style in F# is for short variable names, and I'm all for that for the most part, but I think in this case we can/should make them a bit clearer.

let rec exhaust n factor =
    match n % factor with
    | 0L -&gt; exhaust (n / factor) factor
    | _ -&gt; n

let rec primeFactors' = function
    | 1L, _, factors -&gt; factors
    | n, factor, factors -&gt;
        let m = exhaust n factor
        primeFactors' (m, factor + 1L, if n &lt;&gt; m then factor::factors else factors)

let primeFactors n =
    primeFactors' (n, 2L, []) |&gt; List.rev