Reputation: 7986
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))
Upvotes: 6
Views: 7015
Reputation: 63
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]
(Unless you dealing with huge numbers of course....)
Upvotes: 3
Reputation: 243041
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.
Upvotes: 5
Reputation: 545528
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))
Upvotes: 9
Reputation: 118865
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)
Upvotes: 3