创建无限懒惰列表的问题

时间:2015-02-10 15:15:22

标签: f# c#-to-f#

我在F#中完成了第七个欧拉问题*,但对我的不满意 实现。在函数primes中,我创建了一个我估计包含第10,001个素数的序列。当我尝试使用Seq.initInfinite懒惰地生成候选素数时,我的代码只是在抛出内存异常之前挂起。

有人可以建议我用延迟生成的序列替换文字序列,一旦找到所需的素数,该序列会被短路吗?

let isPrime n =
    let bound = int (sqrt (float n))
         seq {2 .. bound} |> Seq.forall (fun x -> n % x <> 0)

let primeAsync n =
    async { return (n, isPrime n)}  

let primes =
    {1..1000000}
         |> Seq.map primeAsync
         |> Async.Parallel
         |> Async.RunSynchronously
         |> Array.filter snd
         |> Array.map fst
         |> Array.mapi (fun i el -> (i, el))    
         |> Array.find (fun (fst, snd) -> fst = 10001)

primes

*“通过列出前六个素数:2,3,5,7,11和13,我们可以看到第6个素数是13.什么是第10,001个素数?”

2 个答案:

答案 0 :(得分:2)

我认为问题在于Async.RunSynchronously是不是懒惰并且试图评估整个无限序列。虽然有更好的解决方案,但你的算法足够快,所以你甚至不需要并行化;这非常有效:

open System

let isPrime n =
    let bound = n |> float |> sqrt |> int
    seq {2 .. bound} |> Seq.forall (fun x -> n % x <> 0)

let prime =   
   Seq.initInfinite ((+) 2)
      |> Seq.filter isPrime
      |> Seq.skip 10000
      |> Seq.head

答案 1 :(得分:2)

一旦将序列提供给Async.Parallel,序列就会被“提升”。如果要最小化内存消耗,请按顺序运行计算或将其拆分为延迟块,每个块中的元素将并行运行。