Seq.unfold explanation in F#

*爱你&永不变心* 提交于 2020-01-03 17:15:35

问题


I am trying to create a sequence lazily by using F#.

The sequence is defined as follows:

The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangle numbers are:

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

Here is what I have so far but it dosn't seem to work:

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

Thank you very much who can help me figure out how unfold works. Thanks

Edit: I marked the first answer as correct but it dosnt work, however I slightly modified it and it worked.

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

回答1:


First off, why do you use match if you've got only one case?

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

Second, what “doesn't seem to work”? Are you aware that you produce an infinite list?

/Edit: For completeness’ sake, here’s the correct solution, which the OP found himself and posted as a comment:

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



回答2:


Another alternative to the code that Brian posted is to use recursion instead of imperative 'while' loop:

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)

It is far less efficient (so you have to be a bit careful here...), but it is more idiomatic functional solution, so it may be easier to see what the code does.




回答3:


Here is an alternative:

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)



回答4:


I know this is a pretty old one, but i cant figure out why using float when you are sure that x * (x + 1) is an even number and indeed divisible by 2. So I would simply use this one instead (not much difference i know but at least you have an 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

(Unless you dealing with huge numbers of course....)



来源:https://stackoverflow.com/questions/533633/seq-unfold-explanation-in-f

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!