You can compare your approach with my solution to the Euler 10 problem
let rec primes = Seq.cache <| seq { yield 2; yield! Seq.unfold nextPrime 3 } and nextPrime n = if isPrime n then Some(n, n + 2) else nextPrime(n + 2) and isPrime n = if n >= 2 then primes |> Seq.tryFind (fun x -> n % x = 0 || x * x > n) |> fun x -> x.Value * x.Value > n else false
It is purely functional, uses a cashing sequence optimized for authentication; it also gives a very useful function isPrime n as a joint result.
And applies to the original problem
let problem010 () = primes |> Seq.takeWhile ((>) 2000000) |> (Seq.map int64 >> Seq.sum)
it ends in a decent 2.5 s . It doesn't work fast, but is good enough to use this sequence of primes in several of my other Project Euler solutions (27, 35, 37, 50, 58, 69, 70, 77).
What is missing in your decision - from your code, I believe that you create a completely new sequence for each prim internal call, that is, for every natural call, while my approach uses single for primes already found and only lists its cached instance when creating each next prime number.
source share