F#中的Seq.unfold解释

时间:2009-02-10 18:51:03

标签: f# seq.unfold

我正在尝试使用F#懒惰地创建一个序列。

序列定义如下:

  

序列的第n个术语   三角形数字由,tn =给出   ½n(N + 1);所以前十个三角形   数字是:

     

1,3,6,10,15,21,28,36,45,55,   ...

这是我到目前为止所做的,但似乎无法发挥作用:

let tri_seq = 1.0 |> Seq.unfold (fun x -> match x with                                         
                                          | _ -> Some (x, 0.5*x*(x + 1.0)))

非常感谢谁能帮我弄清楚展开的效果。感谢

编辑:我将第一个答案标记为正确,但它确实有效,但是我稍微修改了它并且有效。

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0),x + 1.0))

4 个答案:

答案 0 :(得分:8)

首先,如果您只有一个案例,为什么要使用match

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (x, 0.5 * x * (x + 1.0)))

其次,什么“似乎不起作用”?你知道你产生了无限的名单吗?

/编辑:为了完整起见,这是正确的解决方案,OP发现自己并发布评论:

let tri_seq = 
    1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0), x + 1.0))

答案 1 :(得分:4)

Brian发布的代码的另一种替代方法是使用递归而不是命令式“while”循环:

let tri = 
  let rec loop(n, diff) = seq { 
    yield n        
    yield! loop(n + diff, diff + 1.0) }
  loop(1.0, 2.0)
printfn "%A" (tri |> Seq.take 10 |> Seq.to_list)

效率低得多(所以你必须要小心一点......),但这是更惯用的功能解决方案,因此可能更容易看到代码的功能。

答案 2 :(得分:2)

这是另一种选择:

let tri = seq {
    let n = ref 1.0
    let diff = ref 2.0
    while true do
        yield !n
        n := !n + !diff
        diff := !diff + 1.0
    }

printfn "%A" (tri |> Seq.take 10 |> Seq.to_list)

答案 3 :(得分:1)

我知道这是一个非常古老的,但是当你确定x *(x + 1)是偶数且可以被2整除时,我无法弄清楚为什么使用float。 所以我会简单地使用这一个(我知道的差别不大,但至少你有一个int seq):

let tri_seq = 1 |> Seq.unfold (fun x -> Some (x * (x + 1) / 2 , x + 1)) 

tri_seq |> Seq.take 6 |> Seq.toList //[1; 3; 6; 10; 15; 21]

fiddle

(除非你处理大量的课程......)