无限的斐波那契序列

时间:2014-04-07 13:50:16

标签: f# functional-programming fibonacci lazy-sequences

我正在尝试使用序列模仿H#中着名的F#无限斐波纳契列表。为什么以下序列没有按预期进行评估?它是如何评估的?

let rec fibs = lazy (Seq.append 
                        (Seq.ofList [0;1]) 
                        ((Seq.map2 (+) (fibs.Force()) 
                                       (Seq.skip 1 (fibs.Force())))))

4 个答案:

答案 0 :(得分:9)

问题是你的代码仍然不够懒:在访问结果之前评估Seq.append的参数,但是评估第二个参数(Seq.map2 ...)需要评估自己的参数,它会强制定义相同的惰性值。这可以 通过使用Seq.delay函数解决了问题。您也可以放弃lazy封包,list已经seq,因此您不需要Seq.ofList

let rec fibs = 
    Seq.append [0;1]
        (Seq.delay (fun () -> Seq.map2 (+) fibs (Seq.skip 1 fibs)))

但是,我个人建议使用一个序列表达式,我觉得它更舒服(更容易正确编写):

let rec fibs = seq {
    yield 0
    yield 1
    yield! Seq.map2 (+) fibs (fibs |> Seq.skip 1)
}

答案 1 :(得分:6)

要添加到kvb的答案,您还可以使用Seq.unfold生成(懒惰)序列:

let fibs = Seq.unfold (fun (a, b) -> Some(a+b, (b, a+b))) (0, 1)

val fibs:seq< int>

答案 2 :(得分:3)

另一种方式:

let rec fib = seq { yield 0; yield! Seq.scan (+) 1 fib }

答案 3 :(得分:2)

除了@kvb的回答:如果你只是想要懒惰而不一定是zip技巧,你可以这样做:

let fibs = Seq.unfold (fun (m,n) -> Some (m, (n,n+m))) (0,1)  

这使得Seq.take n fibs及时运行O(n)。

相关问题