Возможно, вы захотите сравнить свой подход с моим вариантом решения задачи Эйлера 10
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
Он чисто функциональный, использует кэширование последовательности, оптимизировано для проверки простоты;Кроме того, он дает очень полезную isPrime n
функцию в качестве побочного результата.
И, будучи применен к исходной задаче
let problem010 () =
primes
|> Seq.takeWhile ((>) 2000000)
|> (Seq.map int64 >> Seq.sum)
, он завершается за приличные 2,5 с .Это не слишком быстро, но было достаточно хорошо, чтобы использовать эту последовательность primes
в нескольких моих других решениях Project Euler (пока 27, 35, 37, 50, 58, 69, 70, 77).
Относительно того, что вам не хватает в вашем решении - из вашего кода я считаю, что вы строите совершенно новую последовательность при каждом внутреннем вызове на prim
, то есть для каждого естественного, в то время как мой подход использует single последовательность для уже найденных простых чисел, и только перечисляет свой кэшированный экземпляр при создании каждого следующего простого числа.